mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-10 12:24:20 +01:00
WIP add eslint and use material-ui
This commit is contained in:
parent
e90e840a60
commit
bc32ede2b5
10
.eslintrc
Normal file
10
.eslintrc
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "airbnb",
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
|
||||
}
|
||||
}
|
916
package-lock.json
generated
916
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -4,6 +4,8 @@
|
||||
"homepage": ".",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^3.9.2",
|
||||
"@material-ui/icons": "^3.0.2",
|
||||
"connected-react-router": "^6.3.1",
|
||||
"ipfs": "~0.33.0",
|
||||
"moment": "^2.24.0",
|
||||
@ -16,15 +18,19 @@
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-scripts": "2.1.8",
|
||||
"redux": "^4.0.1",
|
||||
"redux-saga": "^1.0.2",
|
||||
"semantic-ui-css": "^2.4.1",
|
||||
"semantic-ui-react": "^0.85.0"
|
||||
"redux-saga": "^1.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build"
|
||||
"build": "react-scripts build",
|
||||
"lint": "eslint src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "5.12.0",
|
||||
"eslint-config-airbnb": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.1",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"redux-immutable-state-invariant": "^2.1.0"
|
||||
},
|
||||
"browserslist": [
|
||||
|
@ -4,7 +4,6 @@ import Boards from '../containers/Boards'
|
||||
import OpenBoard from '../containers/OpenBoard'
|
||||
import WithBoard from '../containers/WithBoard'
|
||||
import BoardPage from '../components/BoardPage'
|
||||
import 'semantic-ui-css/semantic.css'
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
|
@ -1,108 +1,145 @@
|
||||
import React from 'react'
|
||||
import Post from './Post'
|
||||
import { Divider, Icon, Grid, Header, List, Button, Card } from 'semantic-ui-react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React from 'react';
|
||||
import {
|
||||
Grid,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
Divider,
|
||||
Button,
|
||||
CardActions,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
Add,
|
||||
Link as LinkIcon,
|
||||
Usb,
|
||||
NetworkCell,
|
||||
NetworkCheck,
|
||||
CloudDownload,
|
||||
Edit,
|
||||
Assignment,
|
||||
Mail,
|
||||
ArrowLeft,
|
||||
} from '@material-ui/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import moment from 'moment';
|
||||
import { shortenAddress } from '../utils/orbitdb';
|
||||
import moment from 'moment'
|
||||
import Post from './Post';
|
||||
|
||||
export default function Board({ address, posts, metadata, replicating, stats, replicationInfo, lastReplicated }) {
|
||||
const { email, website, title, description } = metadata || {}
|
||||
const peerCount = (stats.peers || []).length
|
||||
const online = peerCount > 0
|
||||
const writeable = stats.access ? (stats.access.writeable ? 'Yes' : 'No') : '?'
|
||||
let replicationMessage = lastReplicated ? ('Last Activity at ' + moment(lastReplicated).format('H:mm')) : 'No Activity'
|
||||
if (replicating) {
|
||||
if (replicationInfo && replicationInfo.max !== undefined) {
|
||||
replicationMessage = 'Progress: ' + (replicationInfo.progress || 0) + '/' + replicationInfo.max
|
||||
} else {
|
||||
replicationMessage = 'Initializing Transfer'
|
||||
}
|
||||
export default function Board({
|
||||
address, posts, metadata, replicating, stats, replicationInfo, lastReplicated,
|
||||
}) {
|
||||
const {
|
||||
email, website, title, description,
|
||||
} = metadata || {};
|
||||
const peerCount = (stats.peers || []).length;
|
||||
const online = peerCount > 0;
|
||||
const writeable = stats.access ? (stats.access.writeable ? 'Yes' : 'No') : '?';
|
||||
let replicationMessage = lastReplicated ? (`Last Activity at ${moment(lastReplicated).format('H:mm')}`) : 'No Activity';
|
||||
if (replicating) {
|
||||
if (replicationInfo && replicationInfo.max !== undefined) {
|
||||
replicationMessage = `Progress: ${replicationInfo.progress || 0}/${replicationInfo.max}`;
|
||||
} else {
|
||||
replicationMessage = 'Initializing Transfer';
|
||||
}
|
||||
return <Grid container divided colums={2}>
|
||||
<Grid.Column width={8}>
|
||||
<Header size='large' style={{marginTop:'.5em'}}>
|
||||
<Header.Content>{title || 'Unnamed Board'}</Header.Content>
|
||||
<Header.Subheader>Board</Header.Subheader>
|
||||
</Header>
|
||||
{ description ? <p>{description}</p> : null }
|
||||
}
|
||||
return (
|
||||
<Grid container>
|
||||
<Grid item xs="12" md="6">
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={title || 'Unnamed Board'}
|
||||
subheader="Board"
|
||||
/>
|
||||
</Card>
|
||||
<CardContent>
|
||||
{ description ? <p>{description}</p> : null }
|
||||
</CardContent>
|
||||
<CardContent>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemIcon><LinkIcon /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={address}
|
||||
secondary="Address"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Usb /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={`${stats.opLogLength || 0} Entries`}
|
||||
secondary="Size"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><NetworkCell /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={online ? `${peerCount} Connections` : 'No Connections'}
|
||||
secondary={online ? 'Online' : 'Offline'}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><CloudDownload /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={replicationMessage}
|
||||
secondary={replicating ? 'Downloading' : 'Download'}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Edit /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={writeable}
|
||||
secondary="Write Access"
|
||||
/>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
<List relaxed>
|
||||
<List.Item>
|
||||
<List.Icon name='linkify' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Address</List.Header>
|
||||
<List.Content>
|
||||
{address}
|
||||
</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='disk outline' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Size</List.Header>
|
||||
<List.Content>{stats.opLogLength || 0} Entries</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name={online ? 'heart' : 'heartbeat'} size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>{online ? 'Online' : 'Offline'}</List.Header>
|
||||
<List.Content>{online ? peerCount + ' Connections' : 'No Connections'}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon color={replicating ? 'green' : null} name='feed' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>{replicating ? 'Downloading' : 'Download'}</List.Header>
|
||||
<List.Content>{replicationMessage}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='edit' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Write Access</List.Header>
|
||||
<List.Content>{writeable}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<Divider/>
|
||||
<List.Item>
|
||||
<List.Icon name='file text outline' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Posts</List.Header>
|
||||
<List.Content>{Object.values(posts || {}).length}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='globe' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Website</List.Header>
|
||||
<List.Content>{website ? <a href={website} target="__blank">{website}</a> : 'N/A'}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='mail' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Mail</List.Header>
|
||||
<List.Content>{email ? <a href={'mailto:'+email}>{email}</a> : 'N/A'}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List>
|
||||
<div className='ui three buttons basic'>
|
||||
<Button as={Link} to={'/'}>
|
||||
<Icon name='left arrow'/> Boards
|
||||
</Button>
|
||||
<Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/edit'}>
|
||||
<Icon name='pencil'/> Edit
|
||||
</Button>
|
||||
<Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/p/new'}>
|
||||
<Icon name='plus'/> New Post
|
||||
</Button>
|
||||
</div>
|
||||
</Grid.Column>
|
||||
<Grid.Column width={8}>
|
||||
<Card.Group className="centered" style={{marginTop:'.5em'}}>
|
||||
{Object.keys(posts || {}).map(i => <Post key={posts[i].multihash} {...posts[i]}/>)}
|
||||
</Card.Group>
|
||||
</Grid.Column>
|
||||
<ListItem>
|
||||
<ListItemIcon><Assignment /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={Object.values(posts || {}).length}
|
||||
secondary="Posts"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><NetworkCheck /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={website ? <a href={website} target="__blank">{website}</a> : 'N/A'}
|
||||
secondary="Website"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Mail /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={email ? <a href={`mailto:${email}`}>{email}</a> : 'N/A'}
|
||||
secondary="Email"
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button as={Link} to="/">
|
||||
<ArrowLeft />
|
||||
{' '}
|
||||
Boards
|
||||
</Button>
|
||||
<Button disabled={!writeable} as={Link} to={`${shortenAddress(address)}/edit`}>
|
||||
<Edit />
|
||||
{' '}
|
||||
Edit
|
||||
</Button>
|
||||
<Button disabled={!writeable} as={Link} to={`${shortenAddress(address)}/p/new`}>
|
||||
<Add />
|
||||
{' '}
|
||||
New Post
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Grid>
|
||||
<Grid xs="12" md="6">
|
||||
{Object.keys(posts || {}).map(i => <Post key={posts[i].multihash} {...posts[i]} />)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1,85 +1,81 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Icon, Container, Card, Form, Button } from 'semantic-ui-react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardActions,
|
||||
TextField,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
Save,
|
||||
ArrowLeft,
|
||||
} from '@material-ui/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { shortenAddress } from '../utils/orbitdb';
|
||||
|
||||
export default class BoardEditorForm extends Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
title: props.title || '',
|
||||
website: props.website || '',
|
||||
email: props.email || ''
|
||||
}
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
title: props.title || '',
|
||||
website: props.website || '',
|
||||
email: props.email || '',
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, website, email } = this.state
|
||||
const { address, updateBoardMetadata } = this.props
|
||||
return <Container>
|
||||
<Card fluid centered style={{marginTop:'5em',maxWidth:'40em'}}>
|
||||
<Card.Content>
|
||||
<Card.Header>Edit Board</Card.Header>
|
||||
<Card.Meta>
|
||||
Boards is an experimental peer to peer application.<br/>
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.<br/>
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content>
|
||||
<Form>
|
||||
<Form.Field>
|
||||
<label>Title</label>
|
||||
<input
|
||||
value={title}
|
||||
onChange={this.updateTitle.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Group widths="equal">
|
||||
<Form.Field>
|
||||
<label>Website</label>
|
||||
<input
|
||||
value={website}
|
||||
onChange={this.updateWebsite.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>Email</label>
|
||||
<input
|
||||
value={email}
|
||||
type="email"
|
||||
onChange={this.updateEmail.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
</Form.Group>
|
||||
<div className="ui two buttons">
|
||||
<Button as={Link} to={shortenAddress(address)}>
|
||||
<Icon name="arrow left"/> Back
|
||||
</Button>
|
||||
<Button type="submit" onClick={() => updateBoardMetadata(address, this.state)}>
|
||||
<Icon name="save"/> Save
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Container>
|
||||
}
|
||||
handleChange = name => (event) => {
|
||||
this.setState({
|
||||
[name]: event.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
updateTitle(event) {
|
||||
const title = event.target.value
|
||||
this.setState({ title })
|
||||
}
|
||||
|
||||
updateWebsite(event) {
|
||||
const website = event.target.value
|
||||
this.setState({ website })
|
||||
}
|
||||
|
||||
updateEmail(event) {
|
||||
const email = event.target.value
|
||||
this.setState({ email })
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { title, website, email } = this.state;
|
||||
const { address, updateBoardMetadata } = this.props;
|
||||
return (
|
||||
<Card fluid centered style={{ marginTop: '5em', maxWidth: '40em' }}>
|
||||
<CardHeader>Edit Board</CardHeader>
|
||||
<CardContent>
|
||||
Boards is an experimental peer to peer application.
|
||||
<br />
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.
|
||||
<br />
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</CardContent>
|
||||
<CardContent>
|
||||
<TextField
|
||||
label="Title"
|
||||
value={title}
|
||||
onChange={this.handleChange('title')}
|
||||
/>
|
||||
<TextField
|
||||
label="Website"
|
||||
value={website}
|
||||
onChange={this.handleChange('website')}
|
||||
/>
|
||||
<TextField
|
||||
label="Email"
|
||||
value={email}
|
||||
type="email"
|
||||
onChange={this.handleChange('email')}
|
||||
/>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button as={Link} to={shortenAddress(address)}>
|
||||
<ArrowLeft />
|
||||
{' '}
|
||||
Back
|
||||
</Button>
|
||||
<Button type="submit" onClick={() => updateBoardMetadata(address, this.state)}>
|
||||
<Save />
|
||||
{' '}
|
||||
Save
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,20 @@
|
||||
import React from 'react'
|
||||
import { Switch, Route } from 'react-router-dom'
|
||||
import Board from '../containers/Board'
|
||||
import BoardEditor from '../containers/BoardEditor'
|
||||
import PostEditor from '../containers/PostEditor'
|
||||
import WithStats from '../containers/WithStats'
|
||||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import Board from '../containers/Board';
|
||||
import BoardEditor from '../containers/BoardEditor';
|
||||
import PostEditor from '../containers/PostEditor';
|
||||
import WithStats from '../containers/WithStats';
|
||||
|
||||
function BoardPage({ match, address, posts, metadata }) {
|
||||
return <Switch>
|
||||
<Route path={match.path+'p/new'} component={PostEditor} />
|
||||
<Route path={match.path+'edit'} component={BoardEditor} />
|
||||
<Route path={match.path} component={WithStats(Board)} />
|
||||
function BoardPage({
|
||||
match, address, posts, metadata,
|
||||
}) {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path={`${match.path}p/new`} component={PostEditor} />
|
||||
<Route path={`${match.path}edit`} component={BoardEditor} />
|
||||
<Route path={match.path} component={WithStats(Board)} />
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
export default BoardPage
|
||||
export default BoardPage;
|
||||
|
@ -1,73 +1,105 @@
|
||||
import React from '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 React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
Grid,
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
CardActions,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Avatar,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
AccountBox,
|
||||
CastConnected,
|
||||
Wifi,
|
||||
Usb,
|
||||
VerifiedUser,
|
||||
Lock,
|
||||
Code,
|
||||
Add,
|
||||
Comment,
|
||||
} from '@material-ui/icons';
|
||||
import BoardsItem from './BoardsItem';
|
||||
|
||||
export default function Boards({ stats, boards, createBoard, closeBoard }) {
|
||||
return <Grid container divided colums={2}>
|
||||
<Grid.Column width={8}>
|
||||
<Header size='large' style={{marginTop:'.5em'}}>
|
||||
<Icon name="cube" color="blue" circular/>
|
||||
<Header.Content>
|
||||
<Header.Content>IPFS Boards</Header.Content>
|
||||
<Header.Subheader>Experimental Build</Header.Subheader>
|
||||
</Header.Content>
|
||||
</Header>
|
||||
<Divider />
|
||||
<List relaxed>
|
||||
<List.Item>
|
||||
<List.Icon name='leaf' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Seeding</List.Header>
|
||||
<List.Content>{Object.keys(boards).length} Boards</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='signal' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Connected Peers</List.Header>
|
||||
<List.Content>{stats.peers.length}</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>Not Supported Yet</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name='user circle' size="large" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>IPFS ID</List.Header>
|
||||
<List.Content>{stats.id}</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 style={{wordBreak:'break-all'}}>{stats.pubKey}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
export default function Boards({
|
||||
stats, boards, createBoard, closeBoard,
|
||||
}) {
|
||||
return (
|
||||
<Grid>
|
||||
<Grid item xs="12" md="8">
|
||||
<Card>
|
||||
<CardHeader
|
||||
avatar={<Avatar><AccountBox /></Avatar>}
|
||||
title="IPFS Boards"
|
||||
subheader="Experimental Build"
|
||||
/>
|
||||
<CardContent>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemIcon><CastConnected /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={Object.keys(boards).length}
|
||||
secondary="Seeding"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Wifi /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={stats.peers.length}
|
||||
secondary="Connected Peers"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Usb /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Not supported yet"
|
||||
secondary="Used Space"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><VerifiedUser /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={stats.id}
|
||||
secondary="IPFS ID"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Lock /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={stats.pubKey}
|
||||
secondary="OrbitDB Public Key"
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
<div className="ui three buttons">
|
||||
<Button as='a' href="https://github.com/fazo96/ipfs-boards" target="__blank" >
|
||||
<Icon name="github"/> GitHub
|
||||
</Button>
|
||||
<Button as={Link} to={'/b/new'}>
|
||||
<Icon name="plus"/> Add Board
|
||||
</Button>
|
||||
<Button as='a' href="https://github.com/fazo96/ipfs-boards/issues/new" target="__blank">
|
||||
<Icon name="comment"/> Leave Feedback
|
||||
</Button>
|
||||
</div>
|
||||
</Grid.Column>
|
||||
<Grid.Column width={8} style={{paddingTop:'3em'}}>
|
||||
<Card.Group className="centered">
|
||||
{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>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button as="a" href="https://github.com/fazo96/ipfs-boards" target="__blank">
|
||||
<Code />
|
||||
{' '}
|
||||
GitHub
|
||||
</Button>
|
||||
<Button as={Link} to="/b/new">
|
||||
<Add />
|
||||
{' '}
|
||||
Add Board
|
||||
</Button>
|
||||
<Button as="a" href="https://github.com/fazo96/ipfs-boards/issues/new" target="__blank">
|
||||
<Comment />
|
||||
{' '}
|
||||
Leave Feedback
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
{Object.values(boards).map(board => <BoardsItem key={board.address} closeBoard={closeBoard} {...board} />)}
|
||||
{Object.keys(boards).length === 0 && 'No boards opened'}
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1,43 +1,61 @@
|
||||
import React from 'react'
|
||||
import { Icon, List, Button, Card } from 'semantic-ui-react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { shortenAddress } from '../utils/orbitdb'
|
||||
import React from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardActions,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
ArrowLeft,
|
||||
Assignment,
|
||||
} from '@material-ui/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { shortenAddress } from '../utils/orbitdb';
|
||||
|
||||
export default function BoardsItem({ address, metadata, name, closeBoard }) {
|
||||
return <Card fluid>
|
||||
<Card.Content>
|
||||
<Card.Header>
|
||||
{ metadata.title || 'Unnamed board' }
|
||||
</Card.Header>
|
||||
<Card.Meta>Board</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content>
|
||||
<List>
|
||||
<List.Item>
|
||||
<List.Icon name="hashtag" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Name</List.Header>
|
||||
<List.Content>{name}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name="chain" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Address</List.Header>
|
||||
<List.Content>{address}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List>
|
||||
</Card.Content>
|
||||
<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>
|
||||
export default function BoardsItem({
|
||||
address, metadata, name, closeBoard,
|
||||
}) {
|
||||
return (
|
||||
<Card fluid>
|
||||
<CardHeader
|
||||
title={metadata.title || 'Unnamed board'}
|
||||
subheader="Board"
|
||||
/>
|
||||
<Card.Content>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemIcon name="hashtag" verticalAlign="middle" />
|
||||
<ListItemText>
|
||||
<List.Header>Name</List.Header>
|
||||
<ListItemText>{name}</ListItemText>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon name="chain" verticalAlign="middle" />
|
||||
<ListItemText>
|
||||
<List.Header>Address</List.Header>
|
||||
<ListItemText>{address}</ListItemText>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Card.Content>
|
||||
<CardActions>
|
||||
<Button onClick={() => closeBoard(address)}>
|
||||
<ArrowLeft />
|
||||
{' '}
|
||||
Close
|
||||
</Button>
|
||||
<Button as={Link} to={shortenAddress(address)}>
|
||||
<Assignment />
|
||||
{' '}
|
||||
View
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1,55 +1,71 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Icon, Container, Card, Form, Button } from 'semantic-ui-react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
CardActions,
|
||||
TextField,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
Add,
|
||||
ArrowLeft,
|
||||
} from '@material-ui/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default class OpenBoardForm extends Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
address: props.address || ''
|
||||
}
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
address: props.address || '',
|
||||
};
|
||||
}
|
||||
|
||||
updateAddress(event) {
|
||||
const address = event.target.value
|
||||
this.setState({ address })
|
||||
}
|
||||
updateAddress = (event) => {
|
||||
const address = event.target.value;
|
||||
this.setState({ address });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { address } = this.state
|
||||
const { openBoard, opening } = this.props
|
||||
return <Container>
|
||||
<Card fluid centered style={{marginTop:'5em',maxWidth:'40em'}}>
|
||||
<Card.Content>
|
||||
<Card.Header>Open a Board</Card.Header>
|
||||
<Card.Meta>
|
||||
Boards is an experimental peer to peer application.<br/>
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.<br/>
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content>
|
||||
<Form loading={opening}>
|
||||
<Form.Field>
|
||||
<input
|
||||
placeholder="Paste an existing address or write your new board ID"
|
||||
value={address}
|
||||
onChange={this.updateAddress.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<div className="ui two buttons">
|
||||
<Button as={Link} to={'/'}>
|
||||
<Icon name="arrow left"/> Back
|
||||
</Button>
|
||||
<Button type="submit" onClick={() => openBoard({ address, redirect: true })}>
|
||||
<Icon name="plus"/> Open
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Container>
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { address } = this.state;
|
||||
const { openBoard, opening } = this.props;
|
||||
return (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Card>
|
||||
<CardHeader
|
||||
title="Open a Board"
|
||||
/>
|
||||
<CardContent>
|
||||
Boards is an experimental peer to peer application.
|
||||
<br />
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.
|
||||
<br />
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</CardContent>
|
||||
<CardContent>
|
||||
<TextField
|
||||
placeholder="Paste an existing address or write your new board ID"
|
||||
value={address}
|
||||
onChange={this.updateAddress}
|
||||
disabled={opening}
|
||||
/>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button as={Link} to="/">
|
||||
<ArrowLeft />
|
||||
{' '}
|
||||
Back
|
||||
</Button>
|
||||
<Button type="submit" disabled={opening} onClick={() => openBoard({ address, redirect: true })}>
|
||||
<Add />
|
||||
{' '}
|
||||
Open
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,47 @@
|
||||
import React from 'react'
|
||||
import { List, Card } from 'semantic-ui-react'
|
||||
import React from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from '@material-ui/core';
|
||||
import { Comment, Link as LinkIcon } from '@material-ui/icons';
|
||||
|
||||
export default function Post({ title, multihash, pubKey }) {
|
||||
return <Card fluid>
|
||||
<Card.Content>
|
||||
<Card.Header>
|
||||
{title}
|
||||
</Card.Header>
|
||||
<Card.Meta>Post</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content style={{wordBreak:'break-all'}}>
|
||||
<List>
|
||||
<List.Item>
|
||||
<List.Icon name="key" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Signed By</List.Header>
|
||||
<List.Content>{pubKey || 'Unknown'}</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name="comments" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Comments</List.Header>
|
||||
<List.Content>Not Supported Yet</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Icon name="chain" verticalAlign="middle"/>
|
||||
<List.Content>
|
||||
<List.Header>Content</List.Header>
|
||||
<List.Content>
|
||||
<a href={'//ipfs.io/ipfs/'+multihash}>{multihash}</a>
|
||||
</List.Content>
|
||||
</List.Content>
|
||||
</List.Item>
|
||||
</List>
|
||||
</Card.Content>
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={title}
|
||||
subheader="Post"
|
||||
/>
|
||||
<CardContent style={{ wordBreak: 'break-all' }}>
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemIcon name="key" verticalAlign="middle" />
|
||||
<ListItemText
|
||||
primary={pubKey || 'Unknown'}
|
||||
secondary="Signed By"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><Comment /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary="Not supported yet"
|
||||
secondary="Comments"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<ListItemIcon><LinkIcon /></ListItemIcon>
|
||||
<ListItemText
|
||||
primary={<a href={`//ipfs.io/ipfs/${multihash}`}>{multihash}</a>}
|
||||
secondary="Content"
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</CardContent>
|
||||
</Card>
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1,71 +1,90 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Card, Container, Form, Icon, Button } from 'semantic-ui-react'
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardActions,
|
||||
CardHeader,
|
||||
TextField,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
Link as LinkIcon,
|
||||
Save,
|
||||
ArrowLeft,
|
||||
} from '@material-ui/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { shortenAddress } from '../utils/orbitdb';
|
||||
|
||||
export default class PostForm extends Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
title: props.title || '',
|
||||
content: props.content || ''
|
||||
}
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
title: props.title || '',
|
||||
content: props.content || '',
|
||||
};
|
||||
}
|
||||
|
||||
updateTitle(event) {
|
||||
this.setState({ title: event.target.value })
|
||||
}
|
||||
updateTitle(event) {
|
||||
this.setState({ title: event.target.value });
|
||||
}
|
||||
|
||||
updateContent(event) {
|
||||
this.setState({ content: event.target.value })
|
||||
}
|
||||
updateContent(event) {
|
||||
this.setState({ content: event.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, content } = this.state
|
||||
const { onSave, board } = this.props
|
||||
const { address } = board
|
||||
return <Container>
|
||||
<Card fluid centered style={{marginTop:'5em',maxWidth:'40em'}}>
|
||||
<Card.Content>
|
||||
<Card.Header>New Post</Card.Header>
|
||||
<Card.Meta>
|
||||
Boards is an experimental peer to peer application.<br/>
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.<br/>
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</Card.Meta>
|
||||
</Card.Content>
|
||||
<Card.Content extra>
|
||||
<Icon name="chain"/> {address}
|
||||
</Card.Content>
|
||||
<Card.Content>
|
||||
<Form>
|
||||
<Form.Field>
|
||||
<label>Title</label>
|
||||
<input
|
||||
placeholder="What's this about?"
|
||||
value={title}
|
||||
onChange={this.updateTitle.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>Content</label>
|
||||
<input
|
||||
placeholder='Write your thoughts'
|
||||
value={content}
|
||||
onChange={this.updateContent.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Button as={Link} to={shortenAddress(address)}>
|
||||
<Icon name="chevron left"/> Board
|
||||
</Button>
|
||||
<Button type='submit' onClick={() => onSave({ title, text: content })}>
|
||||
<Icon name="save"/> Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</Container>
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { title, content } = this.state;
|
||||
const { onSave, board } = this.props;
|
||||
const { address } = board;
|
||||
return (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Card fluid centered style={{ marginTop: '5em', maxWidth: '40em' }}>
|
||||
<CardHeader
|
||||
title="New Post"
|
||||
/>
|
||||
<CardContent>
|
||||
Boards is an experimental peer to peer application.
|
||||
<br />
|
||||
All content you publish will be public and may be lost or
|
||||
changed at any time.
|
||||
<br />
|
||||
Please do not use this version of Boards
|
||||
for anything other than testing purposes
|
||||
</CardContent>
|
||||
<CardContent>
|
||||
<LinkIcon />
|
||||
{' '}
|
||||
{address}
|
||||
</CardContent>
|
||||
<CardContent>
|
||||
<TextField
|
||||
label="Title"
|
||||
placeholder="What's this about?"
|
||||
value={title}
|
||||
onChange={this.updateTitle}
|
||||
/>
|
||||
<TextField
|
||||
label="Content"
|
||||
placeholder="Write your thoughts"
|
||||
value={content}
|
||||
onChange={this.updateContent}
|
||||
/>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button as={Link} to={shortenAddress(address)}>
|
||||
<ArrowLeft />
|
||||
{' '}
|
||||
Board
|
||||
</Button>
|
||||
<Button type="submit" onClick={() => onSave({ title, text: content })}>
|
||||
<Save />
|
||||
{' '}
|
||||
Submit
|
||||
</Button>
|
||||
|
||||
</CardActions>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { push } from 'react-router-redux'
|
||||
import { push } from 'connected-react-router'
|
||||
import BoardsComponent from '../components/Boards'
|
||||
import WithStats from './WithStats'
|
||||
import { closeBoard } from '../actions/board'
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Dimmer } from 'semantic-ui-react'
|
||||
import { connect } from 'react-redux'
|
||||
import { openBoard } from '../actions/board'
|
||||
import { getBoardAddress } from '../utils/orbitdb'
|
||||
@ -41,9 +40,7 @@ export default function WithBoard(WrappedComponent) {
|
||||
if (board) {
|
||||
return <WrappedComponent {...board} {...this.props} />
|
||||
} else {
|
||||
return <Dimmer page active={true}>
|
||||
Opening this board
|
||||
</Dimmer>
|
||||
return "Opening this board"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { put, call, fork, take } from 'redux-saga/effects'
|
||||
import { eventChannel } from 'redux-saga'
|
||||
import { push } from 'react-router-redux'
|
||||
import { push } from 'connected-react-router'
|
||||
import { open, connectDb } from '../orbitdb'
|
||||
import { createdBoard } from '../actions/board'
|
||||
import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb'
|
||||
|
Loading…
Reference in New Issue
Block a user