mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-10 12:24:20 +01:00
UI Improvements
This commit is contained in:
parent
1a91c3e679
commit
443cef55a5
@ -9,4 +9,5 @@ export const UPDATE_BOARD = 'UPDATE_BOARD'
|
|||||||
export const BOARD_ERROR = 'BOARD_ERROR'
|
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_REPLICATED = 'ORBITDB_REPLICATED'
|
export const ORBITDB_REPLICATED = 'ORBITDB_REPLICATED'
|
@ -4,7 +4,7 @@ import { Divider, Icon, Grid, Segment, Header, List, Button, Card } from 'semant
|
|||||||
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 Board({ address, posts, metadata }) {
|
export default function Board({ address, posts, metadata, replicating }) {
|
||||||
const { email, website, title } = metadata || {}
|
const { email, website, title } = metadata || {}
|
||||||
const url = window.location.href
|
const url = window.location.href
|
||||||
return <Grid container divided colums={2}>
|
return <Grid container divided colums={2}>
|
||||||
@ -39,10 +39,10 @@ export default function Board({ address, posts, metadata }) {
|
|||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='wifi' size="large" verticalAlign="middle"/>
|
<List.Icon color={replicating ? 'green' : null} name='wifi' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Replication Status</List.Header>
|
<List.Header>Replication</List.Header>
|
||||||
<List.Content>Idle</List.Content>
|
<List.Content>{replicating ? 'Receiving Content...' : 'Idle'}</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
@ -60,9 +60,16 @@ export default function Board({ address, posts, metadata }) {
|
|||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
</List>
|
</List>
|
||||||
<div className='ui two buttons'>
|
<div className='ui three buttons basic'>
|
||||||
<Button>Edit</Button>
|
<Button>
|
||||||
<Button as={Link} to={shortenAddress(address)+'/p/new'}>New Post</Button>
|
<Icon name='left arrow'/> Boards
|
||||||
|
</Button>
|
||||||
|
<Button>
|
||||||
|
<Icon name='pencil'/> Edit
|
||||||
|
</Button>
|
||||||
|
<Button as={Link} to={shortenAddress(address)+'/p/new'}>
|
||||||
|
<Icon name='plus'/> New Post
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column width={8}>
|
<Grid.Column width={8}>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { Form, Button } from 'semantic-ui-react'
|
import { Redirect } from 'react-router-dom'
|
||||||
|
import { Container, Card, Form, Button } from 'semantic-ui-react'
|
||||||
|
import { shortenAddress } from '../utils/orbitdb'
|
||||||
|
|
||||||
export default class BoardForm extends Component {
|
export default class BoardForm extends Component {
|
||||||
constructor(props){
|
constructor(props){
|
||||||
@ -16,22 +18,32 @@ export default class BoardForm extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { address } = this.state
|
const { address } = this.state
|
||||||
const { onSave, creating } = this.props
|
const { openBoard, opening } = this.props
|
||||||
return <Form>
|
return <Container>
|
||||||
<Form.Field>
|
<Card fluid centered style={{marginTop:'5em',maxWidth:'40em'}}>
|
||||||
<label>Address</label>
|
<Card.Content>
|
||||||
<input
|
<Card.Header>Open a Board</Card.Header>
|
||||||
placeholder="Paste an existing address or write your new board ID"
|
<Card.Meta>
|
||||||
value={address}
|
Boards is an experimental peer to peer application.<br/>
|
||||||
onChange={this.updateAddress.bind(this)}
|
All content you publish will be public and may be lost or
|
||||||
/>
|
changed at any time.<br/>
|
||||||
</Form.Field>
|
Please do not use this version of Boards
|
||||||
<Button
|
for anything other than testing purposes
|
||||||
type='submit'
|
</Card.Meta>
|
||||||
onClick={() => onSave({ address })}
|
</Card.Content>
|
||||||
disabled={creating}
|
<Card.Content>
|
||||||
>Create</Button>
|
<Form loading={opening}>
|
||||||
{creating ? 'Creating the board...' : ''}
|
<Form.Field>
|
||||||
</Form>
|
<input
|
||||||
|
placeholder="Paste an existing address or write your new board ID"
|
||||||
|
value={address}
|
||||||
|
onChange={this.updateAddress.bind(this)}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
<Button fluid onClick={() => openBoard({ address })}>Open</Button>
|
||||||
|
</Form>
|
||||||
|
</Card.Content>
|
||||||
|
</Card>
|
||||||
|
</Container>
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,67 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Button, Card } from 'semantic-ui-react'
|
import { List, Icon, Segment, Divider, Grid, Header, Button, Card } from 'semantic-ui-react'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
import BoardsItem from './BoardsItem'
|
import BoardsItem from './BoardsItem'
|
||||||
|
|
||||||
export default function Boards({ boards, createBoard }) {
|
export default function Boards({ boards, createBoard }) {
|
||||||
return <div>
|
return <Grid container divided colums={2}>
|
||||||
<Card.Group>
|
<Grid.Column width={8}>
|
||||||
{Object.values(boards).map(board => <BoardsItem key={board.address} {...board} />)}
|
<Header size='large' style={{marginTop:'.5em'}}>
|
||||||
</Card.Group>
|
<Header.Content>IPFS Boards</Header.Content>
|
||||||
<Button onClick={createBoard}>New Board</Button>
|
<Header.Subheader>Experimental Build</Header.Subheader>
|
||||||
</div>
|
</Header>
|
||||||
|
<Divider />
|
||||||
|
<List relaxed>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='file text outline' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Boards</List.Header>
|
||||||
|
<List.Content>{Object.keys(boards).length}</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='wifi' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Connected Peers</List.Header>
|
||||||
|
<List.Content>?</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='disk outline' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Used Space</List.Header>
|
||||||
|
<List.Content>?</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='user' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>IPFS ID</List.Header>
|
||||||
|
<List.Content>?</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='key' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>OrbitDB Public Key</List.Header>
|
||||||
|
<List.Content>?</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
</List>
|
||||||
|
<div className="ui two buttons">
|
||||||
|
<Button as='a' href="https://github.com/fazo96/ipfs-boards">
|
||||||
|
<Icon name="github"/> GitHub
|
||||||
|
</Button>
|
||||||
|
<Button as={Link} to={'/b/new'}>
|
||||||
|
Open or Create Board
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Grid.Column>
|
||||||
|
<Grid.Column width={8} style={{paddingTop:'3em'}}>
|
||||||
|
<Card.Group className="centered">
|
||||||
|
{Object.values(boards).map(board => <BoardsItem key={board.address} {...board} />)}
|
||||||
|
{Object.keys(boards).length === 0 ? <Segment>No boards opened</Segment> : null}
|
||||||
|
</Card.Group>
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
}
|
}
|
@ -4,14 +4,16 @@ import { Link } from 'react-router-dom'
|
|||||||
import { shortenAddress } from '../utils/orbitdb'
|
import { shortenAddress } from '../utils/orbitdb'
|
||||||
|
|
||||||
export default function BoardsItem({ address, title }) {
|
export default function BoardsItem({ address, title }) {
|
||||||
return <Card>
|
return <Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
{ title || 'Untitled board' }
|
{ title || 'Unnamed board' }
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Meta>
|
<Card.Meta>
|
||||||
Board
|
Board
|
||||||
</Card.Meta>
|
</Card.Meta>
|
||||||
|
</Card.Content>
|
||||||
|
<Card.Content>
|
||||||
<Card.Description style={{wordBreak:'break-all'}}>
|
<Card.Description style={{wordBreak:'break-all'}}>
|
||||||
{address}
|
{address}
|
||||||
</Card.Description>
|
</Card.Description>
|
||||||
|
@ -4,7 +4,10 @@ import { Card, Icon } from 'semantic-ui-react'
|
|||||||
export default function Post({ title, multihash}) {
|
export default function Post({ title, multihash}) {
|
||||||
return <Card fluid>
|
return <Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Icon name="file text outline"/> {title}
|
<Card.Header>
|
||||||
|
{title}
|
||||||
|
</Card.Header>
|
||||||
|
<Card.Meta>Post</Card.Meta>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
<Card.Content style={{wordBreak:'break-all'}}>
|
<Card.Content style={{wordBreak:'break-all'}}>
|
||||||
<Icon name="chain"/> <a href={'//ipfs.io/ipfs/'+multihash}>View</a>
|
<Icon name="chain"/> <a href={'//ipfs.io/ipfs/'+multihash}>View</a>
|
||||||
|
@ -3,13 +3,13 @@ import { connect } from 'react-redux'
|
|||||||
import BoardForm from '../components/BoardForm'
|
import BoardForm from '../components/BoardForm'
|
||||||
import { openBoard } from '../actions/board'
|
import { openBoard } from '../actions/board'
|
||||||
|
|
||||||
function BoardEditor({ board, openBoard }) {
|
function BoardEditor(props) {
|
||||||
return <BoardForm board={board} onSave={openBoard} />
|
return <BoardForm {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state){
|
||||||
return {
|
return {
|
||||||
board: state.boardEditor.board
|
opening: state.boardEditor.opening
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,19 +5,16 @@ import {
|
|||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
return {
|
return {
|
||||||
board: {
|
opening: false
|
||||||
name: ''
|
|
||||||
},
|
|
||||||
creating: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BoardEditorReducer(state = getInitialState(), action) {
|
export default function BoardEditorReducer(state = getInitialState(), action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case OPEN_BOARD:
|
case OPEN_BOARD:
|
||||||
return Object.assign({}, state, { board: action.board, opening: true })
|
return Object.assign({}, state, { opening: true })
|
||||||
case OPENED_BOARD:
|
case OPENED_BOARD:
|
||||||
return Object.assign({}, state, { opening: false, board: action.board })
|
return Object.assign({}, state, { opening: false })
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { OPENED_BOARD, UPDATE_BOARD } from '../actions/actionTypes'
|
import { OPENED_BOARD, UPDATE_BOARD, ORBITDB_REPLICATED, ORBITDB_REPLICATE } from '../actions/actionTypes'
|
||||||
import { getBoardIdFromAddress } from '../utils/orbitdb'
|
import { getBoardIdFromAddress } from '../utils/orbitdb'
|
||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
@ -7,20 +7,32 @@ function getInitialState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateBoard(existingBoards, address, value) {
|
||||||
|
return Object.assign({}, existingBoards, {
|
||||||
|
[address]: Object.assign({}, existingBoards[address] || {}, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default function BoardsReducer(state = getInitialState(), action) {
|
export default function BoardsReducer(state = getInitialState(), action) {
|
||||||
let address, newBoards
|
let address
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case OPENED_BOARD:
|
case OPENED_BOARD:
|
||||||
address = action.board.address
|
address = action.board.address
|
||||||
newBoards = Object.assign({}, state.boards, { [address]: action.board })
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, action.board) })
|
||||||
return Object.assign({}, state, { boards: newBoards })
|
|
||||||
case UPDATE_BOARD:
|
case UPDATE_BOARD:
|
||||||
address = action.address
|
address = action.address
|
||||||
let { posts, metadata } = action
|
let { posts, metadata } = action
|
||||||
newBoards = Object.assign({}, state.boards, {
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, { posts, metadata })})
|
||||||
[address]: Object.assign({}, state.boards[address], { posts, metadata })
|
case ORBITDB_REPLICATE:
|
||||||
})
|
address = action.address
|
||||||
return Object.assign({}, state, { boards: newBoards })
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
||||||
|
replicating: true
|
||||||
|
})})
|
||||||
|
case ORBITDB_REPLICATED:
|
||||||
|
address = action.address
|
||||||
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
||||||
|
replicating: false
|
||||||
|
})})
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,13 @@ 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 { creatingBoard, createdBoard, boardError } from '../actions/board'
|
import { creatingBoard, createdBoard, boardError } from '../actions/board'
|
||||||
import { getBoardIdFromAddress } from '../utils/orbitdb'
|
import { getBoardIdFromAddress, shortenAddress } from '../utils/orbitdb'
|
||||||
import { UPDATE_BOARD } from '../actions/actionTypes'
|
import { UPDATE_BOARD } from '../actions/actionTypes'
|
||||||
|
|
||||||
|
export function* goToBoard({ board }){
|
||||||
|
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({
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { takeEvery } from 'redux-saga/effects'
|
import { takeEvery } from 'redux-saga/effects'
|
||||||
import { OPEN_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE } from '../actions/actionTypes'
|
import { OPEN_BOARD, OPENED_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE } from '../actions/actionTypes'
|
||||||
import { openBoard, updateBoard } from './boards'
|
import { openBoard, updateBoard, goToBoard } 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(ADD_POST, addPost)
|
yield takeEvery(ADD_POST, addPost)
|
||||||
yield takeEvery(ORBITDB_WRITE, updateBoard)
|
yield takeEvery(ORBITDB_WRITE, updateBoard)
|
||||||
yield takeEvery(ORBITDB_REPLICATED, updateBoard)
|
yield takeEvery(ORBITDB_REPLICATED, updateBoard)
|
||||||
|
Loading…
Reference in New Issue
Block a user