├── .gitignore
├── .dockerignore
├── slave_build.sh
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── .babelrc
├── .env.development
├── pre_local.sh
├── slave_start.sh
├── .eslintignore
├── reload.sh
├── src
├── reducers
│ ├── init_ipfs.js
│ └── index.js
├── components
│ ├── App.test.js
│ ├── Status.js
│ ├── App.js
│ ├── Upload.js
│ └── See.js
├── actions
│ └── index.js
├── containers
│ ├── Footer.js
│ └── Header.js
├── index.js
└── registerServiceWorker.js
├── .scripts
├── pre_remote.sh
└── post-receive
├── Dockerfile
├── .eslintrc.js
├── index.js
├── README.md
├── package.json
└── .eslintrc
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .env
3 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cube
3 | build
4 | .scripts
--------------------------------------------------------------------------------
/slave_build.sh:
--------------------------------------------------------------------------------
1 |
2 | #!/bin/bash
3 |
4 | APP=$1
5 |
6 | docker build -t "$APP" .
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TalaikisInc/ipfs-uploader/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | ["import", {"libraryName": "antd", "style": true} ]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | SKIP_PREFLIGHT_CHECK=true
2 | NODE_ENV = "development"
3 | CI = true
4 | HTTPS = false
5 |
--------------------------------------------------------------------------------
/pre_local.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git remote -v
4 | git remote add production ssh://root@123.123.123.123/opt/ipfs.git
5 |
--------------------------------------------------------------------------------
/slave_start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | APP=$1
4 | PORT=$2
5 |
6 | docker run -it -p "$PORT:3000" --rm --name "$APP" -d "$APP"
7 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | tmp/**
2 | build/**
3 | node_modules/**
4 | contracts/**
5 | migrations/1_initial_migration.js
6 | migrations/2_deploy_contracts.js
7 |
--------------------------------------------------------------------------------
/reload.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | APP=ipfs
4 | PORT=3004
5 |
6 | ./slave_build.sh "$APP"
7 | docker stop "$APP"
8 | docker rm "$APP"
9 | ./slave_start.sh "$APP" "$PORT"
10 |
--------------------------------------------------------------------------------
/src/reducers/init_ipfs.js:
--------------------------------------------------------------------------------
1 | export default (state = [], action) => {
2 | switch (action.type) {
3 | case 'INIT_IPFS':
4 | return action.payload
5 | default:
6 | return state
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 |
3 | import IPFSReducer from './init_ipfs'
4 |
5 | const rootReducer = combineReducers({
6 | ipfs: IPFSReducer
7 | })
8 |
9 | export default rootReducer
10 |
--------------------------------------------------------------------------------
/.scripts/pre_remote.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd /opt && \
4 | git init --bare ipfs.git && \
5 | git clone ipfs.git ipfs
6 |
7 | cp /root/.scripts/post-receive /opt/ipfs.git/hooks
8 | chmod ug+x /opt/ipfs.git/hooks/post-receive
9 | cp /root/.scripts/.env /opt/ipfs
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM keymetrics/pm2:latest-alpine
2 |
3 | RUN npm i -g pm2
4 |
5 | WORKDIR /var/www/app
6 | COPY ./ ./
7 | RUN npm i
8 |
9 | ENV NODE_ENV production
10 | ENV PORT 3000
11 |
12 | EXPOSE 3000
13 |
14 | RUN npm run build
15 |
16 | CMD ["pm2-runtime", "index.js", "i", "2"]
17 |
--------------------------------------------------------------------------------
/src/components/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import App from './App'
4 |
5 | /*
6 | Full tests
7 | */
8 | it('renders without crashing', () => {
9 | const div = document.createElement('div')
10 | ReactDOM.render(, div)
11 | })
12 |
--------------------------------------------------------------------------------
/src/actions/index.js:
--------------------------------------------------------------------------------
1 | import IPFS from 'ipfs-mini'
2 |
3 | export function initIPFS(payload) {
4 | const ipfs = new IPFS({
5 | host: 'ipfs.infura.io',
6 | port: 5001,
7 | protocol: 'https'
8 | })
9 |
10 | return {
11 | type: 'INIT_IPFS',
12 | payload: ipfs
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "IPFS Uploader",
3 | "name": "IPFS Uploader",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es6: true
5 | },
6 | extends: [
7 | 'standard'
8 | ],
9 | globals: {
10 | Atomics: 'readonly',
11 | SharedArrayBuffer: 'readonly'
12 | },
13 | parserOptions: {
14 | ecmaFeatures: {
15 | jsx: true
16 | },
17 | ecmaVersion: 2018,
18 | sourceType: 'module'
19 | },
20 | plugins: [
21 | 'react'
22 | ],
23 | rules: {
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/containers/Footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux'
3 |
4 | import Box from 'grommet/components/Box'
5 | import Paragraph from 'grommet/components/Paragraph'
6 |
7 | const Footer = () => (
8 |
9 | © 2018, Talaikis Ltd.
10 |
11 | )
12 |
13 | function mapStateToProps(state) {
14 | return { }
15 | }
16 |
17 | export default connect(mapStateToProps)(Footer)
18 |
--------------------------------------------------------------------------------
/src/components/Status.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 |
4 | const Status = (props) => {
5 | return (
6 |
7 | { !props.ipfs
8 | ?
9 | Warning! IPFS isn't initiated by some reason.
10 |
11 | : null
12 | }
13 |
14 | )
15 | }
16 |
17 | function mapStateToProps(state) {
18 | return {
19 | ipfs: state.ipfs
20 | }
21 | }
22 |
23 | export default connect(mapStateToProps)(Status)
24 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const { join } = require('path')
3 | const app = express()
4 |
5 | app.use(require('compression')())
6 | app.use(express.static(join(__dirname, 'build')))
7 |
8 | app.get('/*', (req, res) => {
9 | res.sendFile(join(__dirname, 'build', 'index.html'))
10 | })
11 |
12 | const PORT = process.env.NODE_ENV === 'production' ? process.env.PORT : 3000
13 | app.listen(PORT, '0.0.0.0', (err) => {
14 | if (err) {
15 | console.log(err)
16 | }
17 | console.info(`==> listening on http://localhost:${PORT}.`)
18 | })
19 |
--------------------------------------------------------------------------------
/.scripts/post-receive:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | read_var() {
4 | VAR=$(grep $1 $2 | xargs)
5 | IFS="=" read -ra VAR <<< "$VAR"
6 | echo ${VAR[1]#*=}
7 | }
8 |
9 | APP_NAME=$(read_var APP_NAME /root/.scripts/.env)
10 | PORT=$(read_var PROD_PORT /root/.scripts/.env)
11 |
12 | echo "Triger received. Deploying..."
13 | cd /opt/ipfs
14 | git --git-dir=/opt/ipfs.git --work-tree=/opt/ipfs checkout master -f
15 |
16 | echo 'Installing'
17 | npm install
18 |
19 | echo 'Building...'
20 | PORT=$PORT npm run build
21 |
22 | echo 'Starting server.'
23 | pm2 delete $APP_NAME
24 | PORT=$PORT pm2 start npm --name $APP_NAME -- start
25 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as ReactDOM from 'react-dom'
3 | import { Provider } from 'react-redux'
4 | import { createStore, applyMiddleware } from 'redux'
5 | import thunk from 'redux-thunk'
6 | import reducers from './reducers'
7 |
8 | import App from './components/App'
9 | import registerServiceWorker from './registerServiceWorker'
10 | // import { unregister } from './registerServiceWorker'
11 | const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
12 |
13 | ReactDOM.render(
14 |
15 |
16 | ,
17 | document.getElementById('root')
18 | )
19 |
20 | registerServiceWorker()
21 | // unregister()
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # IPFS Image Uploader
8 |
9 | [](https://www.gnu.org/licenses/gpl-3.0)
10 | [](https://david-dm.org/powerpiper/ipfs-uploader)
11 | [](https://david-dm.org/powerpiper/ipfs-uploader/?type=dev)
12 | [](https://travis-ci.org/powerpiper/ipfs-uploader)
13 |
14 | Upload your images to Interplanetary file system (IPFS) and see them.
15 |
16 | ## Demo
17 |
18 | [Visit](https://ipfs.talaikis.com/upload)
19 |
--------------------------------------------------------------------------------
/src/containers/Header.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { Redirect } from 'react-router'
4 |
5 | import Heading from 'grommet/components/Heading'
6 | import Tabs from 'grommet/components/Tabs'
7 | import Box from 'grommet/components/Box'
8 | import Tab from 'grommet/components/Tab'
9 |
10 | import * as actions from '../actions'
11 |
12 | class Header extends Component {
13 | render () {
14 | return (
15 |
16 | IPFS Image Uploader
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
30 | function mapStateToProps(state) {
31 | return { }
32 | }
33 |
34 | export default connect(mapStateToProps, actions)(Header)
35 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | IPFS Uploader
10 |
11 |
12 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ipfs-uploader",
3 | "version": "0.2.0",
4 | "private": false,
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/TalaikisINc/ipfs-uploader.git"
8 | },
9 | "author": "Tadas Talaikis ",
10 | "license": "GPL-3.0",
11 | "bugs": {
12 | "url": "https://github.com/TalaikisINc/ipfs-uploader/issues"
13 | },
14 | "dependencies": {
15 | "compression": "^1.7.4",
16 | "express": "^4.17.1",
17 | "grommet": "^1.13.0",
18 | "grommet-css": "^1.6.0",
19 | "ipfs-mini": "^1.1.5",
20 | "react": "^16.9.0",
21 | "react-dom": "^16.9.0",
22 | "react-ga": "^2.6.0",
23 | "react-redux": "^7.1.1",
24 | "react-router-dom": "^4.3.1",
25 | "react-scripts": "3.1.1",
26 | "redux": "^4.0.4",
27 | "redux-thunk": "^2.3.0"
28 | },
29 | "scripts": {
30 | "start": "react-scripts start",
31 | "build": "react-scripts build",
32 | "eject": "react-scripts eject",
33 | "analyze": "source-map-explorer build/static/js/main.*",
34 | "cypress:open": "cypress open",
35 | "cypress:run": "cypress run --record",
36 | "test": "jest"
37 | },
38 | "devDependencies": {
39 | "babel-plugin-import": "^1.12.1",
40 | "eslint": "^6.3.0",
41 | "eslint-config-standard": "^14.1.0",
42 | "eslint-plugin-import": "^2.18.2",
43 | "eslint-plugin-node": "^9.2.0",
44 | "eslint-plugin-promise": "^4.2.1",
45 | "eslint-plugin-react": "^7.14.3",
46 | "eslint-plugin-standard": "^4.0.1",
47 | "husky": "^3.0.4",
48 | "jest": "^24.9.0",
49 | "source-map-explorer": "^2.0.1"
50 | },
51 | "browserslist": {
52 | "production": [
53 | ">0.2%",
54 | "not dead",
55 | "not op_mini all"
56 | ]
57 | },
58 | "husky": {
59 | "hooks": {
60 | "pre-commit": "npm run build",
61 | "pre-push": "npm run build"
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { BrowserRouter, Route } from 'react-router-dom'
4 | import ReactGA from 'react-ga'
5 |
6 | import '../../node_modules/grommet-css'
7 | import App from 'grommet/components/App'
8 | import Box from 'grommet/components/Box'
9 |
10 | import * as actions from '../actions'
11 | import Header from '../containers/Header'
12 | import Footer from '../containers/Footer'
13 | import Status from './Status'
14 | import See from './See'
15 | import Upload from './Upload'
16 |
17 | class _App extends Component {
18 | initGA () {
19 | ReactGA.initialize(process.env.GA_TRACKING_ID)
20 | // console.log('Initialized')
21 | }
22 |
23 | logPageView () {
24 | ReactGA.set({ page: window.location.pathname })
25 | ReactGA.pageview(window.location.pathname)
26 | // console.log(`Logged: ${window.location.pathname}`)
27 | }
28 |
29 | componentDidMount () {
30 | this.props.initIPFS()
31 | if (process.env.NODE_ENV === 'production') {
32 | if (!window.GA_INITIALIZED) {
33 | this.initGA()
34 | window.GA_INITIALIZED = true
35 | }
36 | this.logPageView()
37 | }
38 | }
39 |
40 | render() {
41 | return (
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | )
60 | }
61 | }
62 |
63 | function mapStateToProps(state) {
64 | return {
65 | ipfs: state.ipfs
66 | }
67 | }
68 |
69 | export default connect(mapStateToProps, actions)(_App)
70 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | const isLocalhost = Boolean(
2 | window.location.hostname === 'localhost' ||
3 | // [::1] is the IPv6 localhost address.
4 | window.location.hostname === '[::1]' ||
5 | // 127.0.0.1/8 is considered localhost for IPv4.
6 | window.location.hostname.match(
7 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
8 | )
9 | )
10 |
11 | export default function register() {
12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
13 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
14 | if (publicUrl.origin !== window.location.origin) {
15 | return
16 | }
17 |
18 | window.addEventListener('load', () => {
19 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
20 |
21 | if (isLocalhost) {
22 | checkValidServiceWorker(swUrl)
23 |
24 | navigator.serviceWorker.ready.then(() => {
25 | console.log(
26 | 'This web app is being served cache-first by a service ' +
27 | 'worker. To learn more, visit https://goo.gl/SC7cgQ'
28 | )
29 | })
30 | } else {
31 | registerValidSW(swUrl)
32 | }
33 | })
34 | }
35 | }
36 |
37 | function registerValidSW(swUrl) {
38 | navigator.serviceWorker
39 | .register(swUrl)
40 | .then(registration => {
41 | registration.onupdatefound = () => {
42 | const installingWorker = registration.installing
43 | installingWorker.onstatechange = () => {
44 | if (installingWorker.state === 'installed') {
45 | if (navigator.serviceWorker.controller) {
46 | console.log('New content is available; please refresh.')
47 | } else {
48 | console.log('Content is cached for offline use.')
49 | }
50 | }
51 | }
52 | }
53 | })
54 | .catch(error => {
55 | console.error('Error during service worker registration:', error)
56 | })
57 | }
58 |
59 | function checkValidServiceWorker(swUrl) {
60 | fetch(swUrl)
61 | .then(response => {
62 | if (
63 | response.status === 404 ||
64 | response.headers.get('content-type').indexOf('javascript') === -1
65 | ) {
66 | navigator.serviceWorker.ready.then(registration => {
67 | registration.unregister().then(() => {
68 | window.location.reload()
69 | })
70 | })
71 | } else {
72 | registerValidSW(swUrl)
73 | }
74 | })
75 | .catch(() => {
76 | console.log(
77 | 'No internet connection found. App is running in offline mode.'
78 | )
79 | })
80 | }
81 |
82 | export function unregister() {
83 | if ('serviceWorker' in navigator) {
84 | navigator.serviceWorker.ready.then(registration => {
85 | registration.unregister()
86 | })
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/components/Upload.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 |
4 | import Toast from 'grommet/components/Toast'
5 | import Heading from 'grommet/components/Heading'
6 | import Box from 'grommet/components/Box'
7 | import Button from 'grommet/components/Button'
8 | import Label from 'grommet/components/Label'
9 | import Form from 'grommet/components/Form'
10 |
11 | class Put extends Component {
12 | constructor(props) {
13 | super(props)
14 |
15 | this.state = {
16 | hash: '',
17 | success: '',
18 | failure: '',
19 | modalOpen: false,
20 | document: '',
21 | loading: false
22 | }
23 |
24 | this.handleUploadFile = this.handleUploadFile.bind(this)
25 | this.handleSubmit = this.handleSubmit.bind(this)
26 | }
27 |
28 | handleUploadFile(event) {
29 | const data = event.target.files[0]
30 | const name = event.target.name
31 | if (data.type.match('image/*')) {
32 | const reader = new FileReader()
33 | reader.onload = (function(theFile) {
34 | return function(e) {
35 | this.setState({
36 | [name]: e.target.result
37 | })
38 | }.bind(this)
39 | }.bind(this))(data)
40 | reader.readAsDataURL(data)
41 | } else {
42 | this.setState({
43 | modalOpen: true,
44 | failure: `We can accept only image files.`
45 | })
46 | }
47 | }
48 |
49 | handleSubmit(event) {
50 | event.preventDefault()
51 |
52 | this.setState({
53 | loading: true
54 | })
55 |
56 | if (this.state.document !== '') {
57 | this.props.ipfs.addJSON(this.state.document, async (err, _hash) => {
58 | if (err) {
59 | this.setState({
60 | failure: `Error occured: ${err.message}`
61 | })
62 | } else {
63 | this.setState({
64 | modalOpen: true,
65 | hash: _hash,
66 | success: `Success! Your hash: ${_hash}`
67 | })
68 | }
69 | })
70 | } else {
71 | this.setState({
72 | modalOpen: true,
73 | failure: `You need an image.`
74 | })
75 | }
76 |
77 | this.setState({
78 | loading: false
79 | })
80 | }
81 |
82 | render() {
83 | return (
84 |
85 | Upload image to Interplanetary File System (IPFS)
86 |
87 |
96 | { this.state.hash !== '' ? `Note your hash: ${this.state.hash}` : '' }
97 |
98 | { this.state.modalOpen &&
100 | { this.state.success ? this.state.success : null }
101 | { this.state.failure ? this.state.failure : null }
102 |
103 | }
104 |
105 | )
106 | }
107 | }
108 |
109 | function mapStateToProps(state) {
110 | return {
111 | ipfs: state.ipfs
112 | }
113 | }
114 |
115 | export default connect(mapStateToProps)(Put)
116 |
--------------------------------------------------------------------------------
/src/components/See.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 |
4 | import Toast from 'grommet/components/Toast'
5 | import Box from 'grommet/components/Box'
6 | import Heading from 'grommet/components/Heading'
7 | import Label from 'grommet/components/Label'
8 | import Form from 'grommet/components/Form'
9 | import Button from 'grommet/components/Button'
10 | import TextInput from 'grommet/components/TextInput'
11 | import Image from 'grommet/components/Image'
12 |
13 | class Home extends Component {
14 | constructor(props) {
15 | super(props)
16 |
17 | this.state = {
18 | success: '',
19 | failure: '',
20 | modalOpen: false,
21 | hash: '',
22 | data: '',
23 | loading: false
24 | }
25 |
26 | this.handleChange = this.handleChange.bind(this)
27 | this.handleSubmit = this.handleSubmit.bind(this)
28 | }
29 |
30 | handleChange(event) {
31 | const value = event.target.value ? event.target.value : ''
32 |
33 | this.setState({
34 | [event.target.name]: value
35 | })
36 | }
37 |
38 | handleSubmit(event) {
39 | event.preventDefault()
40 |
41 | this.setState({
42 | loading: true
43 | })
44 |
45 | if (this.state.hash !== '') {
46 | this.props.ipfs.catJSON(this.state.hash, async (err, data) => {
47 | if(err) {
48 | // console.log(err)
49 | this.setState({
50 | modalOpen: true,
51 | failure: `Error occured: ${err.message}`
52 | })
53 | } else {
54 | this.setState({
55 | data: data
56 | })
57 | }
58 | })
59 | } else {
60 | this.setState({
61 | modalOpen: true,
62 | failure: `You need to enter IPFS hash.`
63 | })
64 | }
65 |
66 | this.setState({
67 | loading: false
68 | })
69 | }
70 |
71 | render() {
72 | return (
73 |
74 |
75 | Load data from IPFS
76 |
95 | { this.state.data ?
96 | : ''
97 | }
98 |
99 |
102 |
103 | https://ipfs.infura.io:5001/api/v0/cat/{this.state.hash}
104 |
105 |
106 |
107 | { this.state.modalOpen &&
109 | { this.state.success ? this.state.success : null }
110 | { this.state.failure ? this.state.failure : null }
111 |
112 | }
113 |
114 | )
115 | }
116 | }
117 |
118 | function mapStateToProps(state) {
119 | return {
120 | ipfs: state.ipfs
121 | }
122 | }
123 |
124 | export default connect(mapStateToProps)(Home)
125 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true
5 | },
6 | "plugins": [
7 | "jsx-a11y"
8 | ],
9 | "extends": [
10 | "plugin:jsx-a11y/recommended"
11 | ],
12 | "parserOptions": {
13 | "ecmaVersion": 6,
14 | "ecmaFeatures": {
15 | "jsx": true
16 | }
17 | },
18 | "rules": {
19 | "comma-dangle": [2, "never"],
20 | "computed-property-spacing": [2, "never"],
21 | "no-cond-assign": 2,
22 | "no-constant-condition": 2,
23 | "no-control-regex": 2,
24 | "no-debugger": 2,
25 | "no-dupe-keys": 2,
26 | "no-empty": 2,
27 | "no-empty-character-class": 2,
28 | "no-ex-assign": 2,
29 | "no-extra-boolean-cast": 2,
30 | "no-extra-parens": 0,
31 | "no-extra-semi": 2,
32 | "no-func-assign": 2,
33 | "no-inner-declarations": 2,
34 | "no-invalid-regexp": 2,
35 | "no-irregular-whitespace": 2,
36 | "no-negated-in-lhs": 2,
37 | "no-obj-calls": 2,
38 | "no-regex-spaces": 2,
39 | "no-reserved-keys": 0,
40 | "no-sparse-arrays": 2,
41 | "no-unreachable": 2,
42 | "use-isnan": 2,
43 | "valid-jsdoc": 0,
44 | "valid-typeof": 2,
45 | "block-scoped-var": 2,
46 | "complexity": 0,
47 | "consistent-return": 2,
48 | "curly": 2,
49 | "default-case": 2,
50 | "eqeqeq": 2,
51 | "guard-for-in": 2,
52 | "no-alert": 2,
53 | "no-caller": 2,
54 | "no-confusing-arrow": 2,
55 | "no-div-regex": 2,
56 | "no-eq-null": 2,
57 | "no-eval": 2,
58 | "no-extend-native": 2,
59 | "no-extra-bind": 2,
60 | "no-fallthrough": 2,
61 | "no-floating-decimal": 2,
62 | "no-implied-eval": 2,
63 | "no-iterator": 2,
64 | "no-labels": 2,
65 | "no-lone-blocks": 2,
66 | "no-loop-func": 2,
67 | "no-multi-spaces": 2,
68 | "no-multi-str": 2,
69 | "no-native-reassign": 2,
70 | "no-new": 2,
71 | "no-new-func": 2,
72 | "no-new-wrappers": 2,
73 | "no-octal": 2,
74 | "no-octal-escape": 2,
75 | "no-proto": 2,
76 | "no-redeclare": 2,
77 | "no-return-assign": 2,
78 | "no-script-url": 2,
79 | "no-self-compare": 2,
80 | "no-sequences": 2,
81 | "no-unused-expressions": 2,
82 | "no-void": 0,
83 | "no-warning-comments": 2,
84 | "no-with": 2,
85 | "prefer-arrow-callback": 2,
86 | "radix": 2,
87 | "vars-on-top": 0,
88 | "wrap-iife": 2,
89 | "prefer-const": 2,
90 | "no-catch-shadow": 2,
91 | "no-const-assign": 2,
92 | "no-delete-var": 2,
93 | "no-label-var": 2,
94 | "no-shadow": 2,
95 | "no-shadow-restricted-names": 2,
96 | "no-undef": 2,
97 | "no-undef-init": 2,
98 | "no-unused-vars": 0,
99 | "no-use-before-define": 2,
100 | "no-var": 2,
101 | "indent": [2, 2, {
102 | "SwitchCase": 1
103 | }],
104 | "arrow-spacing": 2,
105 | "camelcase": 0,
106 | "comma-spacing": 2,
107 | "comma-style": 2,
108 | "consistent-this": 0,
109 | "eol-last": 2,
110 | "func-names": 0,
111 | "func-style": 0,
112 | "key-spacing": [2, {
113 | "beforeColon": false,
114 | "afterColon": true
115 | }],
116 | "max-nested-callbacks": 0,
117 | "new-parens": 2,
118 | "no-array-constructor": 2,
119 | "no-inline-comments": 0,
120 | "no-lonely-if": 2,
121 | "no-mixed-spaces-and-tabs": 2,
122 | "no-new-object": 2,
123 | "semi-spacing": [2, {
124 | "before": false,
125 | "after": true
126 | }],
127 | "no-spaced-func": 2,
128 | "no-ternary": 0,
129 | "no-trailing-spaces": 2,
130 | "no-multiple-empty-lines": 2,
131 | "no-underscore-dangle": 0,
132 | "one-var": 0,
133 | "operator-assignment": [2, "always"],
134 | "padded-blocks": [2, { "blocks": "never", "classes": "never", "switches": "never" }],
135 | "quotes": [2, "single"],
136 | "quote-props": [2, "as-needed"],
137 | "semi": [2, "never"],
138 | "keyword-spacing": 2,
139 | "space-before-blocks": 2,
140 | "object-curly-spacing": [2, "always"],
141 | "array-bracket-spacing": [2, "never"],
142 | "space-in-parens": 2,
143 | "space-unary-ops": 2,
144 | "spaced-comment": 2,
145 | "wrap-regex": 0,
146 | "space-before-function-paren": 0
147 | }
148 | }
--------------------------------------------------------------------------------