mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-03-12 21:48:39 +01:00
eslint fix
This commit is contained in:
parent
bc32ede2b5
commit
4e880f8864
@ -1,23 +1,23 @@
|
|||||||
|
|
||||||
export const ADD_POST = 'ADD_POST'
|
export const ADD_POST = 'ADD_POST';
|
||||||
export const EDIT_POST = 'EDIT_POST'
|
export const EDIT_POST = 'EDIT_POST';
|
||||||
export const HIDE_POST = 'HIDE_POST'
|
export const HIDE_POST = 'HIDE_POST';
|
||||||
export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA'
|
export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA';
|
||||||
|
|
||||||
export const ADD_COMMENT = 'ADD_COMMENT'
|
export const ADD_COMMENT = 'ADD_COMMENT';
|
||||||
export const EDIT_COMMENT = 'EDIT_COMMENT'
|
export const EDIT_COMMENT = 'EDIT_COMMENT';
|
||||||
export const HIDE_COMMENT = 'HIDE_COMMENT'
|
export const HIDE_COMMENT = 'HIDE_COMMENT';
|
||||||
|
|
||||||
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 CLOSE_BOARD = 'CLOSE_BOARD'
|
export const CLOSE_BOARD = 'CLOSE_BOARD';
|
||||||
|
|
||||||
export const UPDATE_BOARD = 'UPDATE_BOARD'
|
export const UPDATE_BOARD = 'UPDATE_BOARD';
|
||||||
|
|
||||||
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'
|
export const ERROR = 'ERROR';
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
import {
|
import {
|
||||||
OPEN_BOARD,
|
OPEN_BOARD,
|
||||||
CLOSE_BOARD,
|
CLOSE_BOARD,
|
||||||
OPENED_BOARD,
|
OPENED_BOARD,
|
||||||
UPDATE_BOARD_METADATA
|
UPDATE_BOARD_METADATA,
|
||||||
} from './actionTypes'
|
} from './actionTypes';
|
||||||
|
|
||||||
export function openBoard(board) {
|
export function openBoard(board) {
|
||||||
return {
|
return {
|
||||||
type: OPEN_BOARD,
|
type: OPEN_BOARD,
|
||||||
board
|
board,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createdBoard(board) {
|
export function createdBoard(board) {
|
||||||
return {
|
return {
|
||||||
type: OPENED_BOARD,
|
type: OPENED_BOARD,
|
||||||
board
|
board,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateBoardMetadata(address, metadata) {
|
export function updateBoardMetadata(address, metadata) {
|
||||||
return {
|
return {
|
||||||
type: UPDATE_BOARD_METADATA,
|
type: UPDATE_BOARD_METADATA,
|
||||||
address,
|
address,
|
||||||
metadata
|
metadata,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function closeBoard(address) {
|
export function closeBoard(address) {
|
||||||
return {
|
return {
|
||||||
type: CLOSE_BOARD,
|
type: CLOSE_BOARD,
|
||||||
address
|
address,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
import { HIDE_COMMENT, ADD_COMMENT, EDIT_COMMENT } from './actionTypes'
|
import { HIDE_COMMENT, ADD_COMMENT, EDIT_COMMENT } from './actionTypes';
|
||||||
|
|
||||||
export function addComment(address, postId, comment, replyTo = 'post') {
|
export function addComment(address, postId, comment, replyTo = 'post') {
|
||||||
return {
|
return {
|
||||||
type: ADD_COMMENT,
|
type: ADD_COMMENT,
|
||||||
address,
|
address,
|
||||||
postId,
|
postId,
|
||||||
comment,
|
comment,
|
||||||
replyTo
|
replyTo,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editComment(address, postId, commentId, comment, replyTo = 'post') {
|
export function editComment(address, postId, commentId, comment, replyTo = 'post') {
|
||||||
return {
|
return {
|
||||||
type: EDIT_COMMENT,
|
type: EDIT_COMMENT,
|
||||||
address,
|
address,
|
||||||
postId,
|
postId,
|
||||||
commentId,
|
commentId,
|
||||||
comment,
|
comment,
|
||||||
replyTo
|
replyTo,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hideComment(address, postId, commentId, replyTo = 'post') {
|
export function hideComment(address, postId, commentId, replyTo = 'post') {
|
||||||
return {
|
return {
|
||||||
type: HIDE_COMMENT,
|
type: HIDE_COMMENT,
|
||||||
address,
|
address,
|
||||||
postId,
|
postId,
|
||||||
commentId,
|
commentId,
|
||||||
replyTo
|
replyTo,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
import { ADD_POST, EDIT_POST, HIDE_POST } from './actionTypes'
|
import { ADD_POST, EDIT_POST, HIDE_POST } from './actionTypes';
|
||||||
|
|
||||||
export function addPost(address, post) {
|
export function addPost(address, post) {
|
||||||
return {
|
return {
|
||||||
type: ADD_POST,
|
type: ADD_POST,
|
||||||
post,
|
post,
|
||||||
address
|
address,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editPost(address, postId, post) {
|
export function editPost(address, postId, post) {
|
||||||
return {
|
return {
|
||||||
type: EDIT_POST,
|
type: EDIT_POST,
|
||||||
address,
|
address,
|
||||||
postId,
|
postId,
|
||||||
post,
|
post,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hidePost(address, postId) {
|
export function hidePost(address, postId) {
|
||||||
return {
|
return {
|
||||||
type: HIDE_POST,
|
type: HIDE_POST,
|
||||||
address,
|
address,
|
||||||
postId
|
postId,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Switch, Route, withRouter } from 'react-router-dom'
|
import { Switch, Route, withRouter } from 'react-router-dom';
|
||||||
import Boards from '../containers/Boards'
|
import Boards from '../containers/Boards';
|
||||||
import OpenBoard from '../containers/OpenBoard'
|
import OpenBoard from '../containers/OpenBoard';
|
||||||
import WithBoard from '../containers/WithBoard'
|
import WithBoard from '../containers/WithBoard';
|
||||||
import BoardPage from '../components/BoardPage'
|
import BoardPage from './BoardPage';
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/b/new' component={OpenBoard} />
|
<Route path="/b/new" component={OpenBoard} />
|
||||||
<Route path='/b/:hash/:name/' component={withRouter(WithBoard(BoardPage))} />
|
<Route path="/b/:hash/:name/" component={withRouter(WithBoard(BoardPage))} />
|
||||||
<Route path='/' component={Boards} />
|
<Route path="/" component={Boards} />
|
||||||
</Switch>
|
</Switch>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(App)
|
export default withRouter(App);
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { connect } from 'react-redux'
|
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({ stats, location, match, boards }) {
|
function Board({
|
||||||
const { hash, name } = match.params
|
stats, location, match, boards,
|
||||||
const address = getBoardAddress(hash, name)
|
}) {
|
||||||
const boardStats = stats.dbs[address] || {}
|
const { hash, name } = match.params;
|
||||||
return <BoardComponent stats={boardStats} {...boards[address]} />
|
const address = getBoardAddress(hash, name);
|
||||||
|
const boardStats = stats.dbs[address] || {};
|
||||||
|
return <BoardComponent stats={boardStats} {...boards[address]} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
boards: state.boards.boards
|
boards: state.boards.boards,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps
|
mapStateToProps,
|
||||||
)(Board)
|
)(Board);
|
||||||
|
@ -1,35 +1,39 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux';
|
||||||
import BoardEditorForm from '../components/BoardEditorForm'
|
import BoardEditorForm from '../components/BoardEditorForm';
|
||||||
import { updateBoardMetadata } from '../actions/board'
|
import { updateBoardMetadata } from '../actions/board';
|
||||||
import { getBoardAddress } from '../utils/orbitdb'
|
import { getBoardAddress } from '../utils/orbitdb';
|
||||||
|
|
||||||
function BoardEditor({ boards, boardEditor, match, updateBoardMetadata }) {
|
function BoardEditor({
|
||||||
const { hash, name } = match.params
|
boards, boardEditor, match, updateBoardMetadata,
|
||||||
const address = getBoardAddress(hash, name)
|
}) {
|
||||||
const board = boards[address]
|
const { hash, name } = match.params;
|
||||||
return <BoardEditorForm
|
const address = getBoardAddress(hash, name);
|
||||||
board={board}
|
const board = boards[address];
|
||||||
address={address}
|
return (
|
||||||
updateBoardMetadata={updateBoardMetadata}
|
<BoardEditorForm
|
||||||
{...board.metadata}
|
board={board}
|
||||||
|
address={address}
|
||||||
|
updateBoardMetadata={updateBoardMetadata}
|
||||||
|
{...board.metadata}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
boards: state.boards.boards
|
boards: state.boards.boards,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
updateBoardMetadata: (address, metadata) => dispatch(updateBoardMetadata(address, metadata))
|
updateBoardMetadata: (address, metadata) => dispatch(updateBoardMetadata(address, metadata)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
)(BoardEditor)
|
)(BoardEditor);
|
||||||
|
@ -1,34 +1,36 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux';
|
||||||
import { push } from 'connected-react-router'
|
import { push } from 'connected-react-router';
|
||||||
import BoardsComponent from '../components/Boards'
|
import BoardsComponent from '../components/Boards';
|
||||||
import WithStats from './WithStats'
|
import WithStats from './WithStats';
|
||||||
import { closeBoard } from '../actions/board'
|
import { closeBoard } from '../actions/board';
|
||||||
|
|
||||||
const WrappedComponent = WithStats(BoardsComponent)
|
const WrappedComponent = WithStats(BoardsComponent);
|
||||||
|
|
||||||
function Boards({ boards, createBoard, closeBoard }) {
|
function Boards({ boards, createBoard, closeBoard }) {
|
||||||
return <WrappedComponent
|
return (
|
||||||
boards={boards}
|
<WrappedComponent
|
||||||
createBoard={createBoard}
|
boards={boards}
|
||||||
closeBoard={closeBoard}
|
createBoard={createBoard}
|
||||||
|
closeBoard={closeBoard}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
boards: state.boards.boards
|
boards: state.boards.boards,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch){
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
createBoard: () => dispatch(push('/b/new')),
|
createBoard: () => dispatch(push('/b/new')),
|
||||||
closeBoard: address => dispatch(closeBoard(address)),
|
closeBoard: address => dispatch(closeBoard(address)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
)(Boards)
|
)(Boards);
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux';
|
||||||
import OpenBoardForm from '../components/OpenBoardForm'
|
import OpenBoardForm from '../components/OpenBoardForm';
|
||||||
import { openBoard } from '../actions/board'
|
import { openBoard } from '../actions/board';
|
||||||
|
|
||||||
function OpenBoard(props) {
|
function OpenBoard(props) {
|
||||||
return <OpenBoardForm {...props} />
|
return <OpenBoardForm {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
opening: state.openBoard.opening
|
opening: state.openBoard.opening,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
openBoard: board => dispatch(openBoard(board))
|
openBoard: board => dispatch(openBoard(board)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
)(OpenBoard)
|
)(OpenBoard);
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux';
|
||||||
import PostForm from '../components/PostForm'
|
import PostForm from '../components/PostForm';
|
||||||
import { addPost } from '../actions/post'
|
import { addPost } from '../actions/post';
|
||||||
import { getBoardAddress } from '../utils/orbitdb';
|
import { getBoardAddress } from '../utils/orbitdb';
|
||||||
|
|
||||||
class PostEditor extends Component {
|
class PostEditor extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { post, addPost, match, boards } = this.props
|
const {
|
||||||
const address = getBoardAddress(match.params.hash, match.params.name)
|
post, addPost, match, boards,
|
||||||
const board = boards[address]
|
} = this.props;
|
||||||
return <PostForm post={post} board={board} onSave={p => addPost(address, p)} />
|
const address = getBoardAddress(match.params.hash, match.params.name);
|
||||||
}
|
const board = boards[address];
|
||||||
|
return <PostForm post={post} board={board} onSave={p => addPost(address, p)} />;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
post: state.postEditor.post,
|
post: state.postEditor.post,
|
||||||
boards: state.boards.boards
|
boards: state.boards.boards,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
addPost: (address, post) => dispatch(addPost(address, post))
|
addPost: (address, post) => dispatch(addPost(address, post)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
)(PostEditor)
|
)(PostEditor);
|
||||||
|
@ -1,53 +1,50 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from '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';
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
boards: state.boards.boards
|
boards: state.boards.boards,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch){
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
openBoard: address => dispatch(openBoard({ address, redirect: false }))
|
openBoard: address => dispatch(openBoard({ address, redirect: false })),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WithBoard(WrappedComponent) {
|
export default function WithBoard(WrappedComponent) {
|
||||||
class ToExport extends Component {
|
class ToExport extends Component {
|
||||||
|
componentDidMount() {
|
||||||
componentDidMount() {
|
const { boards, match } = this.props;
|
||||||
const { boards, match } = this.props
|
const address = getBoardAddress(match.params.hash, match.params.name);
|
||||||
const address = getBoardAddress(match.params.hash, match.params.name)
|
if (!boards[address]) {
|
||||||
if (!boards[address]) {
|
this.props.openBoard(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 <WrappedComponent {...board} {...this.props} />
|
|
||||||
} else {
|
|
||||||
return "Opening this board"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return connect(
|
componentWillReceiveProps({ match, boards }) {
|
||||||
mapStateToProps,
|
const address = getBoardAddress(match.params.hash, match.params.name);
|
||||||
mapDispatchToProps
|
if (!boards[address]) {
|
||||||
)(ToExport)
|
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 <WrappedComponent {...board} {...this.props} />;
|
||||||
|
}
|
||||||
|
return 'Opening this board';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
)(ToExport);
|
||||||
|
}
|
||||||
|
@ -1,43 +1,43 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react';
|
||||||
import { getStats } from '../utils/ipfs'
|
import { getStats } from '../utils/ipfs';
|
||||||
|
|
||||||
export default function(WrappedComponent) {
|
export default function (WrappedComponent) {
|
||||||
return class extends Component {
|
return class extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
stats: {
|
stats: {
|
||||||
id: '?',
|
id: '?',
|
||||||
peers: [],
|
peers: [],
|
||||||
pubKey: '?',
|
pubKey: '?',
|
||||||
dbs: {}
|
dbs: {},
|
||||||
},
|
},
|
||||||
timeout: null
|
timeout: 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() {
|
|
||||||
this.timeout = setTimeout(() => {
|
|
||||||
this.refresh()
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.timeout) clearTimeout(this.timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <WrappedComponent stats={this.state.stats} {...this.props} />
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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() {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.refresh();
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.timeout) clearTimeout(this.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <WrappedComponent stats={this.state.stats} {...this.props} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
34
src/index.js
34
src/index.js
@ -1,13 +1,13 @@
|
|||||||
import 'react-hot-loader/patch'
|
import 'react-hot-loader/patch';
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { render } from 'react-dom'
|
import { render } from 'react-dom';
|
||||||
import { AppContainer } from 'react-hot-loader'
|
import { AppContainer } from 'react-hot-loader';
|
||||||
import configureStore, { history } from './store/configureStore'
|
import { Provider } from 'react-redux';
|
||||||
import App from './components/App'
|
import { ConnectedRouter } from 'connected-react-router';
|
||||||
import registerServiceWorker from './registerServiceWorker'
|
import configureStore, { history } from './store/configureStore';
|
||||||
import { Provider } from 'react-redux'
|
import App from './components/App';
|
||||||
import { ConnectedRouter } from 'connected-react-router'
|
import registerServiceWorker from './registerServiceWorker';
|
||||||
import { start } from './orbitdb'
|
import { start } from './orbitdb';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
@ -19,12 +19,12 @@ render(
|
|||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
</AppContainer>,
|
</AppContainer>,
|
||||||
document.getElementById('root')
|
document.getElementById('root'),
|
||||||
);
|
);
|
||||||
|
|
||||||
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,10 +33,10 @@ if (module.hot) {
|
|||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
</AppContainer>,
|
</AppContainer>,
|
||||||
document.getElementById('root')
|
document.getElementById('root'),
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
registerServiceWorker()
|
registerServiceWorker();
|
||||||
start(store.dispatch)
|
start(store.dispatch);
|
||||||
|
@ -5,4 +5,4 @@ module.exports = {
|
|||||||
ADD_COMMENT: 'ADD_COMMENT',
|
ADD_COMMENT: 'ADD_COMMENT',
|
||||||
UPDATE_COMMENT: 'UPDATE_COMMENT',
|
UPDATE_COMMENT: 'UPDATE_COMMENT',
|
||||||
UPDATE_METADATA: 'UPDATE_METADATA',
|
UPDATE_METADATA: 'UPDATE_METADATA',
|
||||||
};
|
};
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import IPFS from 'ipfs'
|
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';
|
||||||
|
|
||||||
export function isValidID(id) {
|
export function isValidID(id) {
|
||||||
try {
|
try {
|
||||||
if (typeof id === 'string' && multihashes.fromB58String(id)) return true
|
if (typeof id === 'string' && multihashes.fromB58String(id)) return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function start() {
|
export async function start() {
|
||||||
@ -17,96 +17,96 @@ export async function start() {
|
|||||||
window.ipfs = new IPFS({
|
window.ipfs = new IPFS({
|
||||||
repo: 'ipfs-v6-boards-v0',
|
repo: 'ipfs-v6-boards-v0',
|
||||||
EXPERIMENTAL: {
|
EXPERIMENTAL: {
|
||||||
pubsub: true
|
pubsub: true,
|
||||||
}
|
},
|
||||||
|
});
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
window.ipfs.on('ready', () => resolve());
|
||||||
});
|
});
|
||||||
await new Promise(resolve => {
|
|
||||||
window.ipfs.on('ready', () => resolve())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (!window.orbitDb) {
|
if (!window.orbitDb) {
|
||||||
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) {
|
export async function open(address, metadata) {
|
||||||
if (window.dbs && window.dbs[address]) return window.dbs[address]
|
if (window.dbs && window.dbs[address]) return window.dbs[address];
|
||||||
await start()
|
await start();
|
||||||
const options = {
|
const options = {
|
||||||
type: BoardStore.type,
|
type: BoardStore.type,
|
||||||
create: true,
|
create: true,
|
||||||
write: ['*']
|
write: ['*'],
|
||||||
}
|
};
|
||||||
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 = {}
|
if (!window.dbs) window.dbs = {};
|
||||||
window.dbs[db.address.toString()] = db
|
window.dbs[db.address.toString()] = db;
|
||||||
return db
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function connectDb(db, dispatch) {
|
export function connectDb(db, dispatch) {
|
||||||
db.events.on('write', (dbname, hash, entry) => {
|
db.events.on('write', (dbname, hash, entry) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_WRITE',
|
type: 'ORBITDB_WRITE',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString(),
|
address: db.address.toString(),
|
||||||
hash,
|
hash,
|
||||||
entry
|
entry,
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('replicated', address => {
|
db.events.on('replicated', (address) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_REPLICATED',
|
type: 'ORBITDB_REPLICATED',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString()
|
address: db.address.toString(),
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('replicate.progress', (address, hash, entry, progress, have) => {
|
db.events.on('replicate.progress', (address, hash, entry, progress, have) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_REPLICATE_PROGRESS',
|
type: 'ORBITDB_REPLICATE_PROGRESS',
|
||||||
address: db.address.toString(),
|
address: db.address.toString(),
|
||||||
hash,
|
hash,
|
||||||
entry,
|
entry,
|
||||||
progress,
|
progress,
|
||||||
have,
|
have,
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
replicationInfo: Object.assign({}, db._replicationInfo)
|
replicationInfo: Object.assign({}, db._replicationInfo),
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('replicate', address => {
|
db.events.on('replicate', (address) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_REPLICATE',
|
type: 'ORBITDB_REPLICATE',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString()
|
address: db.address.toString(),
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('close', address => {
|
db.events.on('close', (address) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_CLOSE',
|
type: 'ORBITDB_CLOSE',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString()
|
address: db.address.toString(),
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('load', address => {
|
db.events.on('load', (address) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_LOAD',
|
type: 'ORBITDB_LOAD',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString()
|
address: db.address.toString(),
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
db.events.on('load.progress', (address, hash, entry, progress, total) => {
|
db.events.on('load.progress', (address, hash, entry, progress, total) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ORBITDB_LOAD_PROGRESS',
|
type: 'ORBITDB_LOAD_PROGRESS',
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
address: db.address.toString(),
|
address: db.address.toString(),
|
||||||
hash,
|
hash,
|
||||||
entry,
|
entry,
|
||||||
progress,
|
progress,
|
||||||
total
|
total,
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,63 +1,69 @@
|
|||||||
import {
|
import {
|
||||||
OPENED_BOARD,
|
OPENED_BOARD,
|
||||||
CLOSE_BOARD,
|
CLOSE_BOARD,
|
||||||
UPDATE_BOARD,
|
UPDATE_BOARD,
|
||||||
ORBITDB_REPLICATE_PROGRESS,
|
ORBITDB_REPLICATE_PROGRESS,
|
||||||
ORBITDB_REPLICATED,
|
ORBITDB_REPLICATED,
|
||||||
ORBITDB_REPLICATE
|
ORBITDB_REPLICATE,
|
||||||
} from '../actions/actionTypes'
|
} from '../actions/actionTypes';
|
||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
return {
|
return {
|
||||||
boards: {}
|
boards: {},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateBoard(existingBoards, address, value) {
|
function updateBoard(existingBoards, address, value) {
|
||||||
return Object.assign({}, existingBoards, {
|
return Object.assign({}, existingBoards, {
|
||||||
[address]: Object.assign({}, existingBoards[address] || {}, value)
|
[address]: Object.assign({}, existingBoards[address] || {}, value),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteBoard(existingBoards, address) {
|
function deleteBoard(existingBoards, address) {
|
||||||
const boards = Object.assign({}, existingBoards)
|
const boards = Object.assign({}, existingBoards);
|
||||||
delete boards[address]
|
delete boards[address];
|
||||||
return boards
|
return boards;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BoardsReducer(state = getInitialState(), action) {
|
export default function BoardsReducer(state = getInitialState(), action) {
|
||||||
let address
|
let address;
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case OPENED_BOARD:
|
case OPENED_BOARD:
|
||||||
address = action.board.address
|
address = action.board.address;
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, Object.assign({}, action.board, { open: true })) })
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, Object.assign({}, action.board, { open: true })) });
|
||||||
case UPDATE_BOARD:
|
case UPDATE_BOARD:
|
||||||
address = action.address
|
address = action.address;
|
||||||
let { posts, metadata } = action
|
const { posts, metadata } = action;
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, { posts, metadata })})
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, { posts, metadata }) });
|
||||||
case ORBITDB_REPLICATE:
|
case ORBITDB_REPLICATE:
|
||||||
address = action.address
|
address = action.address;
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
return Object.assign({}, state, {
|
||||||
replicating: true
|
boards: updateBoard(state.boards, address, {
|
||||||
})})
|
replicating: true,
|
||||||
case ORBITDB_REPLICATE_PROGRESS:
|
}),
|
||||||
address = action.address
|
});
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
case ORBITDB_REPLICATE_PROGRESS:
|
||||||
replicating: true,
|
address = action.address;
|
||||||
replicationInfo: action.replicationInfo
|
return Object.assign({}, state, {
|
||||||
})})
|
boards: updateBoard(state.boards, address, {
|
||||||
case ORBITDB_REPLICATED:
|
replicating: true,
|
||||||
address = action.address
|
replicationInfo: action.replicationInfo,
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
}),
|
||||||
replicating: false,
|
});
|
||||||
lastReplicated: action.time
|
case ORBITDB_REPLICATED:
|
||||||
})})
|
address = action.address;
|
||||||
case CLOSE_BOARD:
|
return Object.assign({}, state, {
|
||||||
address = action.address
|
boards: updateBoard(state.boards, address, {
|
||||||
return Object.assign({}, state, {
|
replicating: false,
|
||||||
boards: deleteBoard(state.boards, address)
|
lastReplicated: action.time,
|
||||||
})
|
}),
|
||||||
default:
|
});
|
||||||
return state;
|
case CLOSE_BOARD:
|
||||||
}
|
address = action.address;
|
||||||
}
|
return Object.assign({}, state, {
|
||||||
|
boards: deleteBoard(state.boards, address),
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { combineReducers } from 'redux'
|
import { combineReducers } from 'redux';
|
||||||
import { connectRouter} from 'connected-react-router'
|
import { connectRouter } from 'connected-react-router';
|
||||||
import postReducer from './post'
|
import postReducer from './post';
|
||||||
import boardsReducer from './boards'
|
import boardsReducer from './boards';
|
||||||
import openBoardReducer from './openboard'
|
import openBoardReducer from './openboard';
|
||||||
|
|
||||||
export default history => combineReducers({
|
export default history => combineReducers({
|
||||||
router: connectRouter(history),
|
router: connectRouter(history),
|
||||||
postEditor: postReducer,
|
postEditor: postReducer,
|
||||||
boards: boardsReducer,
|
boards: boardsReducer,
|
||||||
openBoard: openBoardReducer
|
openBoard: openBoardReducer,
|
||||||
})
|
});
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
OPEN_BOARD,
|
OPEN_BOARD,
|
||||||
OPENED_BOARD
|
OPENED_BOARD,
|
||||||
} from '../actions/actionTypes'
|
} from '../actions/actionTypes';
|
||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
return {
|
return {
|
||||||
opening: false
|
opening: false,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function openBoardReducer(state = getInitialState(), action) {
|
export default function openBoardReducer(state = getInitialState(), action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case OPEN_BOARD:
|
case OPEN_BOARD:
|
||||||
return Object.assign({}, state, { opening: true })
|
return Object.assign({}, state, { opening: true });
|
||||||
case OPENED_BOARD:
|
case OPENED_BOARD:
|
||||||
return Object.assign({}, state, { opening: false })
|
return Object.assign({}, state, { opening: false });
|
||||||
default:
|
default:
|
||||||
return state
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { ADD_POST } from '../actions/actionTypes'
|
import { ADD_POST } from '../actions/actionTypes';
|
||||||
|
|
||||||
function getInitialState(){
|
function getInitialState() {
|
||||||
return {
|
return {
|
||||||
post: {
|
post: {
|
||||||
title: '',
|
title: '',
|
||||||
content: ''
|
content: '',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function(state = getInitialState(), action) {
|
export default function (state = getInitialState(), action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ADD_POST:
|
case ADD_POST:
|
||||||
return Object.assign({}, state, { post: action.post })
|
return Object.assign({}, state, { post: action.post });
|
||||||
default:
|
default:
|
||||||
return state
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
// This link also includes instructions on opting out of this behavior.
|
// This link also includes instructions on opting out of this behavior.
|
||||||
|
|
||||||
const isLocalhost = Boolean(
|
const isLocalhost = Boolean(
|
||||||
window.location.hostname === 'localhost' ||
|
window.location.hostname === 'localhost'
|
||||||
// [::1] is the IPv6 localhost address.
|
// [::1] is the IPv6 localhost address.
|
||||||
window.location.hostname === '[::1]' ||
|
|| window.location.hostname === '[::1]'
|
||||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
window.location.hostname.match(
|
|| window.location.hostname.match(
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function register() {
|
export default function register() {
|
||||||
@ -40,8 +40,8 @@ export default function register() {
|
|||||||
// service worker/PWA documentation.
|
// service worker/PWA documentation.
|
||||||
navigator.serviceWorker.ready.then(() => {
|
navigator.serviceWorker.ready.then(() => {
|
||||||
console.log(
|
console.log(
|
||||||
'This web app is being served cache-first by a service ' +
|
'This web app is being served cache-first by a service '
|
||||||
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
+ 'worker. To learn more, visit https://goo.gl/SC7cgQ',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -55,7 +55,7 @@ export default function register() {
|
|||||||
function registerValidSW(swUrl) {
|
function registerValidSW(swUrl) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
.then(registration => {
|
.then((registration) => {
|
||||||
registration.onupdatefound = () => {
|
registration.onupdatefound = () => {
|
||||||
const installingWorker = registration.installing;
|
const installingWorker = registration.installing;
|
||||||
installingWorker.onstatechange = () => {
|
installingWorker.onstatechange = () => {
|
||||||
@ -76,7 +76,7 @@ function registerValidSW(swUrl) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
console.error('Error during service worker registration:', error);
|
console.error('Error during service worker registration:', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -84,14 +84,14 @@ function registerValidSW(swUrl) {
|
|||||||
function checkValidServiceWorker(swUrl) {
|
function checkValidServiceWorker(swUrl) {
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
fetch(swUrl)
|
fetch(swUrl)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
if (
|
if (
|
||||||
response.status === 404 ||
|
response.status === 404
|
||||||
response.headers.get('content-type').indexOf('javascript') === -1
|
|| response.headers.get('content-type').indexOf('javascript') === -1
|
||||||
) {
|
) {
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister().then(() => {
|
registration.unregister().then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
@ -103,14 +103,14 @@ function checkValidServiceWorker(swUrl) {
|
|||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log(
|
console.log(
|
||||||
'No internet connection found. App is running in offline mode.'
|
'No internet connection found. App is running in offline mode.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unregister() {
|
export function unregister() {
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister();
|
registration.unregister();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,79 +1,81 @@
|
|||||||
import { put, call, fork, take } from 'redux-saga/effects'
|
import {
|
||||||
import { eventChannel } from 'redux-saga'
|
put, call, fork, take,
|
||||||
import { push } from 'connected-react-router'
|
} from 'redux-saga/effects';
|
||||||
import { open, connectDb } from '../orbitdb'
|
import { eventChannel } from 'redux-saga';
|
||||||
import { createdBoard } from '../actions/board'
|
import { push } from 'connected-react-router';
|
||||||
import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb'
|
import { open, connectDb } from '../orbitdb';
|
||||||
import { UPDATE_BOARD } from '../actions/actionTypes'
|
import { createdBoard } from '../actions/board';
|
||||||
import { saveSaga } from './persistence'
|
import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb';
|
||||||
|
import { UPDATE_BOARD } from '../actions/actionTypes';
|
||||||
|
import { saveSaga } from './persistence';
|
||||||
|
|
||||||
export function* goToBoard({ board }){
|
export function* goToBoard({ board }) {
|
||||||
if (board.redirect) {
|
if (board.redirect) {
|
||||||
yield put(push(shortenAddress(board.address)))
|
yield put(push(shortenAddress(board.address)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* updateBoard({ address }){
|
export function* updateBoard({ address }) {
|
||||||
const db = window.dbs[address]
|
const db = window.dbs[address];
|
||||||
yield put({
|
yield put({
|
||||||
type: UPDATE_BOARD,
|
type: UPDATE_BOARD,
|
||||||
address,
|
address,
|
||||||
posts: db.posts,
|
posts: db.posts,
|
||||||
metadata: Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata
|
metadata: Object.assign({}, db._index._index.metadata), // TODO: fix in lib and use db.metadata
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* closeBoard({ address }){
|
export function* closeBoard({ address }) {
|
||||||
yield call(closeOrbitDBBoard, address)
|
yield call(closeOrbitDBBoard, address);
|
||||||
yield saveSaga()
|
yield saveSaga();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* updateBoardMetadata({ address, metadata }){
|
export function* updateBoardMetadata({ address, metadata }) {
|
||||||
const db = window.dbs[address]
|
const db = window.dbs[address];
|
||||||
if (db) {
|
if (db) {
|
||||||
yield call([db, db.updateMetadata], [metadata])
|
yield call([db, db.updateMetadata], [metadata]);
|
||||||
yield goToBoard({ board: { address } });
|
yield goToBoard({ board: { address } });
|
||||||
} else {
|
} else {
|
||||||
yield put({ type: 'ERROR', error: address + ' not found' })
|
yield put({ type: 'ERROR', error: `${address} not found` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* openBoard({ board }) {
|
export function* openBoard({ board }) {
|
||||||
let db
|
let db;
|
||||||
|
try {
|
||||||
|
const metadata = board.title ? { title: board.title } : null;
|
||||||
|
db = yield call(open, board.address, metadata);
|
||||||
|
} catch (error) {
|
||||||
|
yield put({ type: 'ERROR', error });
|
||||||
|
}
|
||||||
|
if (db) {
|
||||||
|
const address = db.address.toString();
|
||||||
|
const dbInfo = { address };
|
||||||
|
dbInfo.posts = db.posts;
|
||||||
|
dbInfo.metadata = Object.assign({}, db._index._index.metadata); // TODO: fix in lib and use db.metadata
|
||||||
|
dbInfo.name = db.dbname;
|
||||||
try {
|
try {
|
||||||
const metadata = board.title ? { title: board.title } : null
|
const channel = yield call(createDbEventChannel, db);
|
||||||
db = yield call(open, board.address, metadata)
|
yield fork(watchDb, channel);
|
||||||
|
yield put(createdBoard(Object.assign({ redirect: !!board.redirect }, board, dbInfo)));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put({ type: 'ERROR', error })
|
yield put({ type: 'ERROR', error });
|
||||||
}
|
|
||||||
if (db) {
|
|
||||||
const address = db.address.toString()
|
|
||||||
const dbInfo = { address }
|
|
||||||
dbInfo.posts = db.posts
|
|
||||||
dbInfo.metadata = Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata
|
|
||||||
dbInfo.name = db.dbname
|
|
||||||
try {
|
|
||||||
const channel = yield call(createDbEventChannel, db)
|
|
||||||
yield fork(watchDb, channel)
|
|
||||||
yield put(createdBoard(Object.assign({ redirect: !!board.redirect }, board, dbInfo)))
|
|
||||||
} catch (error) {
|
|
||||||
yield put({ type: 'ERROR', error })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* watchDb(channel) {
|
function* watchDb(channel) {
|
||||||
// Dispatches action coming from the channel, terminates when ORBITDB_CLOSE arrives
|
// Dispatches action coming from the channel, terminates when ORBITDB_CLOSE arrives
|
||||||
let action
|
let action;
|
||||||
while(!action || action.type !== 'ORBITDB_CLOSE') {
|
while (!action || action.type !== 'ORBITDB_CLOSE') {
|
||||||
action = yield take(channel)
|
action = yield take(channel);
|
||||||
yield put(action)
|
yield put(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createDbEventChannel(db) {
|
function createDbEventChannel(db) {
|
||||||
return eventChannel(emitter => {
|
return eventChannel((emitter) => {
|
||||||
connectDb(db, emitter)
|
connectDb(db, emitter);
|
||||||
return () => db.close()
|
return () => db.close();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,30 @@
|
|||||||
import { takeEvery, put, call } from 'redux-saga/effects'
|
import { takeEvery, put, call } from 'redux-saga/effects';
|
||||||
import {
|
import {
|
||||||
OPEN_BOARD,
|
OPEN_BOARD,
|
||||||
OPENED_BOARD,
|
OPENED_BOARD,
|
||||||
CLOSE_BOARD,
|
CLOSE_BOARD,
|
||||||
ADD_POST,
|
ADD_POST,
|
||||||
ORBITDB_REPLICATED,
|
ORBITDB_REPLICATED,
|
||||||
ORBITDB_WRITE,
|
ORBITDB_WRITE,
|
||||||
UPDATE_BOARD_METADATA
|
UPDATE_BOARD_METADATA,
|
||||||
} from '../actions/actionTypes'
|
} from '../actions/actionTypes';
|
||||||
import { openBoard, updateBoard, goToBoard, updateBoardMetadata, closeBoard } from './boards'
|
import {
|
||||||
import { addPost } from './posts'
|
openBoard, updateBoard, goToBoard, updateBoardMetadata, closeBoard,
|
||||||
import { openPreviousBoards, saveSaga } from './persistence'
|
} from './boards';
|
||||||
|
import { addPost } from './posts';
|
||||||
|
import { openPreviousBoards, saveSaga } from './persistence';
|
||||||
|
|
||||||
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(OPENED_BOARD, saveSaga)
|
yield takeEvery(OPENED_BOARD, saveSaga);
|
||||||
yield takeEvery(CLOSE_BOARD, closeBoard)
|
yield takeEvery(CLOSE_BOARD, closeBoard);
|
||||||
|
|
||||||
yield takeEvery(ADD_POST, addPost)
|
yield takeEvery(ADD_POST, addPost);
|
||||||
yield takeEvery(UPDATE_BOARD_METADATA, updateBoardMetadata)
|
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);
|
||||||
|
|
||||||
yield openPreviousBoards()
|
yield openPreviousBoards();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { call, put } from 'redux-saga/effects'
|
import { call, put } from 'redux-saga/effects';
|
||||||
import { openBoard } from '../actions/board'
|
import { openBoard } from '../actions/board';
|
||||||
import { save, load } from '../utils/persistence'
|
import { save, load } from '../utils/persistence';
|
||||||
|
|
||||||
export function* openPreviousBoards() {
|
export function* openPreviousBoards() {
|
||||||
const data = yield call(load)
|
const data = yield call(load);
|
||||||
if (Array.isArray(data.addresses)) {
|
if (Array.isArray(data.addresses)) {
|
||||||
for (const address of data.addresses) {
|
for (const address of data.addresses) {
|
||||||
yield put(openBoard({ address, redirect: false }))
|
yield put(openBoard({ address, redirect: false }));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* saveSaga() {
|
export function* saveSaga() {
|
||||||
yield call(save)
|
yield call(save);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { call } from 'redux-saga/effects'
|
import { call } from 'redux-saga/effects';
|
||||||
import { goToBoard } from './boards';
|
import { goToBoard } from './boards';
|
||||||
|
|
||||||
export function* addPost({ address, post }) {
|
export function* addPost({ address, post }) {
|
||||||
const db = window.dbs[address]
|
const db = window.dbs[address];
|
||||||
const { title, text } = post
|
const { title, text } = post;
|
||||||
yield call([db, db.addPost], { title, text })
|
yield call([db, db.addPost], { title, text });
|
||||||
yield goToBoard({ board: { address, redirect: true } });
|
yield goToBoard({ board: { address, redirect: true } });
|
||||||
// TODO: goto post
|
// TODO: goto post
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* editPost({ address, postId, post }) {
|
export function* editPost({ address, postId, post }) {
|
||||||
const db = window.dbs[address]
|
const db = window.dbs[address];
|
||||||
const { title, text } = post
|
const { title, text } = post;
|
||||||
yield call([db, db.updatePost], postId, { title, text })
|
yield call([db, db.updatePost], postId, { title, text });
|
||||||
yield goToBoard({ board: { address, redirect: true } });
|
yield goToBoard({ board: { address, redirect: true } });
|
||||||
// TODO: goto post
|
// TODO: goto post
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {createStore, compose, applyMiddleware} from 'redux';
|
import { createStore, compose, applyMiddleware } from 'redux';
|
||||||
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
|
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
|
||||||
import createSagaMiddleware from 'redux-saga';
|
import createSagaMiddleware from 'redux-saga';
|
||||||
import saga from '../sagas';
|
|
||||||
import createHistory from 'history/createHashHistory';
|
import createHistory from 'history/createHashHistory';
|
||||||
import { routerMiddleware } from 'connected-react-router';
|
import { routerMiddleware } from 'connected-react-router';
|
||||||
|
import saga from '../sagas';
|
||||||
import createRootReducer from '../reducers';
|
import createRootReducer from '../reducers';
|
||||||
|
|
||||||
const sagaMiddleware = createSagaMiddleware();
|
const sagaMiddleware = createSagaMiddleware();
|
||||||
@ -17,9 +17,8 @@ function configureStoreProd(initialState) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const store = createStore(createRootReducer(history), initialState, compose(
|
const store = createStore(createRootReducer(history), initialState, compose(
|
||||||
applyMiddleware(...middlewares)
|
applyMiddleware(...middlewares),
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
||||||
sagaMiddleware.run(saga);
|
sagaMiddleware.run(saga);
|
||||||
|
|
||||||
@ -36,9 +35,8 @@ function configureStoreDev(initialState) {
|
|||||||
|
|
||||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for Redux dev tools
|
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for Redux dev tools
|
||||||
const store = createStore(createRootReducer(history), initialState, composeEnhancers(
|
const store = createStore(createRootReducer(history), initialState, composeEnhancers(
|
||||||
applyMiddleware(...middlewares)
|
applyMiddleware(...middlewares),
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
||||||
let sagaTask = sagaMiddleware.run(saga);
|
let sagaTask = sagaMiddleware.run(saga);
|
||||||
|
|
||||||
|
@ -1,55 +1,55 @@
|
|||||||
export async function ipfsPut(content) {
|
export async function ipfsPut(content) {
|
||||||
const obj = {
|
const obj = {
|
||||||
content: Buffer.from(content),
|
content: Buffer.from(content),
|
||||||
path: '/'
|
path: '/',
|
||||||
}
|
};
|
||||||
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) {
|
export async function readText(multihash) {
|
||||||
const buffer = await window.ipfs.object.get(multihash)
|
const buffer = await window.ipfs.object.get(multihash);
|
||||||
return buffer.toString('utf-8')
|
return buffer.toString('utf-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStats() {
|
export async function getStats() {
|
||||||
const ipfs = window.ipfs;
|
const ipfs = window.ipfs;
|
||||||
const orbitDb = window.orbitDb
|
const orbitDb = window.orbitDb;
|
||||||
const dbs = {}
|
const dbs = {};
|
||||||
const stats = {}
|
const stats = {};
|
||||||
if (ipfs && ipfs.isOnline()) {
|
if (ipfs && ipfs.isOnline()) {
|
||||||
stats.ipfsLoaded = true
|
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 {
|
} else {
|
||||||
stats.ipfsLoaded = false
|
stats.ipfsLoaded = false;
|
||||||
}
|
}
|
||||||
if (stats.ipfsLoaded && orbitDb) {
|
if (stats.ipfsLoaded && orbitDb) {
|
||||||
stats.orbitDbLoaded = true
|
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
|
const writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0;
|
||||||
const dbInfo = {
|
const dbInfo = {
|
||||||
opLogLength: db._oplog.length,
|
opLogLength: db._oplog.length,
|
||||||
access: {
|
access: {
|
||||||
admin: db.access.admin,
|
admin: db.access.admin,
|
||||||
read: db.access.read,
|
read: db.access.read,
|
||||||
write: db.access.write,
|
write: db.access.write,
|
||||||
writeable
|
writeable,
|
||||||
},
|
},
|
||||||
peers: []
|
peers: [],
|
||||||
}
|
};
|
||||||
const subscription = orbitDb._pubsub._subscriptions[db.address]
|
const subscription = orbitDb._pubsub._subscriptions[db.address];
|
||||||
if (subscription && subscription.room) {
|
if (subscription && subscription.room) {
|
||||||
dbInfo.peers = [...(subscription.room._peers || [])]
|
dbInfo.peers = [...(subscription.room._peers || [])];
|
||||||
}
|
}
|
||||||
dbs[db.address] = dbInfo
|
dbs[db.address] = dbInfo;
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
stats.orbitDbLoaded = false
|
stats.orbitDbLoaded = false;
|
||||||
}
|
}
|
||||||
stats.dbs = dbs
|
stats.dbs = dbs;
|
||||||
return stats
|
return stats;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
|
|
||||||
export function getBoardAddress(hash, name) {
|
export function getBoardAddress(hash, name) {
|
||||||
return '/orbitdb/' + hash + '/' + name
|
return `/orbitdb/${hash}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shortenAddress(address) {
|
export function shortenAddress(address) {
|
||||||
return address.replace(/^\/orbitdb/, '/b')
|
return address.replace(/^\/orbitdb/, '/b');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function closeBoard(address) {
|
export function closeBoard(address) {
|
||||||
const db = window.dbs[address]
|
const db = window.dbs[address];
|
||||||
delete window.dbs[address]
|
delete window.dbs[address];
|
||||||
if (db && db.close) db.close()
|
if (db && db.close) db.close();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
|
|
||||||
export function save(){
|
export function save() {
|
||||||
const obj = {
|
const obj = {
|
||||||
addresses: Object.keys(window.dbs || {})
|
addresses: Object.keys(window.dbs || {}),
|
||||||
}
|
};
|
||||||
localStorage.setItem('ipfs-boards-v0', JSON.stringify(obj))
|
localStorage.setItem('ipfs-boards-v0', JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function load(){
|
export function load() {
|
||||||
const str = localStorage.getItem('ipfs-boards-v0')
|
const str = localStorage.getItem('ipfs-boards-v0');
|
||||||
try {
|
try {
|
||||||
return JSON.parse(str) || {};
|
return JSON.parse(str) || {};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {}
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user