Skip to content

Commit

Permalink
feat: add ipfs connection indicator and notifications (ipfs#802)
Browse files Browse the repository at this point in the history
- show the api address when connect via http
- otherwise show api provider (window.ipfs, embedded js-ipfs)
- notify on connection error
- add connected bundle and status indicator
- keep polling api when in the background
- link to release where possible
- auto-reinit ipfs after first failure
- add a retry-init bundle to track ipfs init failures and retry
- Make connection indicator a link to welcome page
- Improve language around network traffic graphs


License: MIT
Signed-off-by: Oli Evans <[email protected]>
  • Loading branch information
olizilla authored Sep 21, 2018
1 parent 1bc6400 commit 3847f78
Show file tree
Hide file tree
Showing 44 changed files with 971 additions and 89 deletions.
410 changes: 405 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"internal-nav-helper": "^1.0.2",
"ipfs-css": "^0.10.0",
"ipfs-geoip": "^2.3.0",
"ipfs-redux-bundle": "^2.0.0",
"ipfs-redux-bundle": "^3.2.0",
"ipfs-unixfs": "^0.1.15",
"ipld-explorer-components": "0.2.0",
"is-binary": "^0.1.0",
Expand Down
1 change: 1 addition & 0 deletions public/locales/cs/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Adresa",
"nodeInfo": "Informace o uzlu",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
1 change: 1 addition & 0 deletions public/locales/de/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addressen",
"nodeInfo": "Node Informationen",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Erweitert",
"publicKey": "Öffentlicher Schlüssel",
Expand Down
7 changes: 7 additions & 0 deletions public/locales/en/notify.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"connectingToIpfs": "Connecting to IPFS",
"connectedToIpfs": "Connected to IPFS",
"ipfsApiRequestFailed": "IPFS request failed. Please check your daemon is running",
"windowIpfsRequestFailed": "IPFS request failed. Please check your IPFS Companion settings",
"ipfsIsBack": "Normal IPFS service has resumed. Enjoy!"
}
6 changes: 4 additions & 2 deletions public/locales/en/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
"addresses": "Addresses",
"nodeInfo": "Node Info",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
"upSpeed": "Up speed",
"downSpeed": "Down speed",
"upSpeed": "Outgoing",
"downSpeed": "Incoming",
"spaceUsed": "Space used",
"networkTraffic": "Network Traffic",
"bandwidthOverTime": "Bandwidth over time",
"bandwidthByPeer": "Bandwidth by peer",
"distributionOfPeers": "Distribution of peers",
Expand Down
1 change: 1 addition & 0 deletions public/locales/es/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addresses",
"nodeInfo": "Información del nodo",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
21 changes: 11 additions & 10 deletions public/locales/fr/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@
"peers": "Pairs",
"addresses": "Adresses",
"nodeInfo": "Info du noeud",
"peerId": "Peer ID",
"peerId": "ID de pair",
"api": "API",
"version": "Version",
"advanced": "Avancé",
"publicKey": "Clé publique",
"upSpeed": "Vitesse envoie",
"downSpeed": "Vitesse réception",
"upSpeed": "Vitesse d'envoi",
"downSpeed": "Vitesse de réception",
"spaceUsed": "Espace utilisé",
"bandwidthOverTime": "Bande passante dans le temps",
"bandwidthOverTime": "Bande passante à travers le temps",
"bandwidthByPeer": "Bande passante par pair",
"distributionOfPeers": "Répartition des pairs",
"rateIn": "Taux entrée",
"rateOut": "Taux sortie",
"totalIn": "Total entrée",
"totalOut": "Total sortie",
"rateIn": "Taux d'entrée",
"rateOut": "Taux de sortie",
"totalIn": "Total d'entrée",
"totalOut": "Total de sortie",
"more": "...et {count} de plus",
"in": "In",
"out": "Out"
"in": "Entrant",
"out": "Sortant"
}
1 change: 1 addition & 0 deletions public/locales/it/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addresses",
"nodeInfo": "Informazioni sul nodo",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
6 changes: 3 additions & 3 deletions public/locales/ko-KR/peers.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"title": "피어들",
"peerId": "Peer ID",
"peerId": "피어 아이디",
"peers": "피어들",
"address": "Address",
"address": "주소",
"location": "위치",
"unknownLocation": "Unknown"
"unknownLocation": "알 수 없음"
}
7 changes: 4 additions & 3 deletions public/locales/ko-KR/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"peers": "피어들",
"addresses": "주소들",
"nodeInfo": "노드 정보",
"peerId": "Peer ID",
"peerId": "피어 아이디",
"api": "API",
"version": "버전",
"advanced": "고급설정",
"publicKey": "공개키",
Expand All @@ -19,6 +20,6 @@
"totalIn": "총 들어온 양",
"totalOut": "총 나간 양",
"more": "…그리고 {count} 더",
"in": "In",
"out": "Out"
"in": "들어옴",
"out": "나감"
}
1 change: 1 addition & 0 deletions public/locales/nl/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addresses",
"nodeInfo": "Node informatie",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
11 changes: 6 additions & 5 deletions public/locales/no/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
"title": "Status",
"peer": "Peer",
"peers": "Peers",
"addresses": "Addresses",
"addresses": "Adresser",
"nodeInfo": "Node Info",
"peerId": "Peer ID",
"version": "Version",
"advanced": "Advanced",
"api": "API",
"version": "Versjon",
"advanced": "Avansert",
"publicKey": "Public Key",
"upSpeed": "Up speed",
"downSpeed": "Down speed",
"upSpeed": "Opplastingshastighet",
"downSpeed": "Nedlastingshastighet",
"spaceUsed": "Space used",
"bandwidthOverTime": "Bandwidth over time",
"bandwidthByPeer": "Bandwidth by peer",
Expand Down
1 change: 1 addition & 0 deletions public/locales/pl/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addresses",
"nodeInfo": "Informacje o węźle",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
1 change: 1 addition & 0 deletions public/locales/pt/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Endereços",
"nodeInfo": "Informação do Nó",
"peerId": "Peer ID",
"api": "API",
"version": "Versão",
"advanced": "Avançado",
"publicKey": "Chave Pública",
Expand Down
1 change: 1 addition & 0 deletions public/locales/sl/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Addresses",
"nodeInfo": "Informacije vozlišča",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
1 change: 1 addition & 0 deletions public/locales/sv/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "Adresser",
"nodeInfo": "Nod-info",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Avancerad",
"publicKey": "Publik nyckel",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-CN/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"addresses": "地址",
"nodeInfo": "节点信息",
"peerId": "Peer ID",
"api": "API",
"version": "Version",
"advanced": "Advanced",
"publicKey": "Public Key",
Expand Down
14 changes: 8 additions & 6 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { connect } from 'redux-bundler-react'
import NavBar from './navigation/NavBar'
import navHelper from 'internal-nav-helper'
import { IpldExploreForm } from 'ipld-explorer-components'
import AsyncRequestLoader from './loader/AsyncRequestLoader'
import { DragDropContext } from 'react-dnd'
import DnDBackend from './lib/dnd-backend'
import ComponentLoader from './loader/ComponentLoader'
import Notify from './components/notify/Notify'
import Connected from './components/connected/Connected'

export class App extends Component {
static propTypes = {
Expand All @@ -34,10 +35,13 @@ export class App extends Component {
<NavBar />
</div>
<div className='flex-auto'>
<div style={{ background: '#F0F6FA', padding: '20px 40px 15px' }}>
<div style={{ maxWidth: 560 }}>
<div className='flex items-center' style={{ background: '#F0F6FA', padding: '20px 40px 15px' }}>
<div className='' style={{ width: 560, maxWidth: '80%' }}>
<IpldExploreForm />
</div>
<div className='flex-auto tr'>
<Connected />
</div>
</div>
<main className='bg-white' style={{ padding: '40px' }}>
{ (ipfsReady || url === '/welcome')
Expand All @@ -47,9 +51,7 @@ export class App extends Component {
</main>
</div>
</div>
<div className='absolute top-0 left-0 pa2'>
<AsyncRequestLoader />
</div>
<Notify />
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/bundles/app-idle.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { debounce, ric, raf } from 'redux-bundler'
const defaults = {
idleTimeout: 2000,
idleAction: 'APP_IDLE',
stopWhenTabInactive: true
stopWhenTabInactive: false
}

const ricOptions = { timeout: 500 }
Expand Down
15 changes: 15 additions & 0 deletions src/bundles/connected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createSelector } from 'redux-bundler'

// We ask for the stats every few seconds, so that gives a good indication
// that ipfs things are working (or not), without additional polling of the api.
const connected = {
name: 'status',
selectIpfsConnected: createSelector(
'selectIpfsReady',
'selectStatsLastSuccess',
'selectStatsLastError',
(ipfsReady, lastSuccess, lastError) => ipfsReady && lastSuccess && lastSuccess > lastError
)
}

export default connected
3 changes: 2 additions & 1 deletion src/bundles/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,11 @@ export default (opts = {}) => {

doFilesFetch: () => async ({ store, ...args }) => {
const isReady = store.selectIpfsReady()
const isConnected = store.selectIpfsConnected()
const isFetching = store.selectFilesIsFetching()
const path = store.selectFilesPathFromHash()

if (isReady && !isFetching && path) {
if (isReady && isConnected && !isFetching && path) {
fetchFiles()({ store, ...args })
}
},
Expand Down
8 changes: 7 additions & 1 deletion src/bundles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import configBundle from './config'
import configSaveBundle from './config-save'
import navbarBundle from './navbar'
import statsBundle from './stats'
import notifyBundle from './notify'
import connectedBundle from './connected'
import retryInitBundle from './retry-init'

export default composeBundles(
appIdle({ idleTimeout: 5000 }),
Expand All @@ -29,5 +32,8 @@ export default composeBundles(
nodeBandwidthBundle,
nodeBandwidthChartBundle(),
peersBundle,
peerLocationsBundle()
peerLocationsBundle(),
notifyBundle,
connectedBundle,
retryInitBundle
)
93 changes: 93 additions & 0 deletions src/bundles/notify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createSelector } from 'redux-bundler'

/*
# Notify
- show error when ipfs goes away.
- show ok when it comes back.
- dismiss the the ok after 3s
*/

const defaultState = {
show: false,
error: false,
eventId: null
}

const notify = {
name: 'notify',

reducer: (state = defaultState, action) => {
if (action.type === 'NOTIFY_DISMISSED') {
return { ...state, show: false }
}

if (action.type.match(/_FETCH_FAILED$/) || action.type.match(/^FILES_\w+_FAILED$/)) {
if (action.type === 'CONFIG_FETCH_FAILED') {
// TODO: this avoids flashing the error message when booting with window.ipfs, but it's very loose.
return state
}
if (state.eventId !== 'FETCH_FAILED') {
return {
...state,
show: true,
error: true,
eventId: 'FETCH_FAILED'
}
}
}

if (action.type.match(/_FETCH_FINISHED$/) || action.type.match(/^FILES_\w+_FINISHED$/)) {
// Finsihing with an error is not a good finish.
// TODO: fix explore bundle to not do that.
if (action.payload && action.payload.error) return state
if (state.eventId === 'FETCH_FAILED') {
return {
...state,
error: false,
eventId: 'FETCH_FINISHED',
lastSuccess: Date.now()
}
}
}

return state
},

selectNotify: state => state.notify,

selectNotifyI18nKey: createSelector(
'selectNotify',
'selectIpfsProvider',
(notify, provider) => {
const { eventId } = notify

if (eventId === 'FETCH_FAILED') {
if (provider === 'window.ipfs') {
return 'windowIpfsRequestFailed'
}
return 'ipfsApiRequestFailed'
}

if (eventId === 'FETCH_FINISHED') {
return 'ipfsIsBack'
}

return eventId
}
),

doNotifyDismiss: () => ({ dispatch }) => dispatch({ type: 'NOTIFY_DISMISSED' }),

// Dismiss the "all ok" message after 3 seconds
reactNotifyOkDismiss: createSelector(
'selectAppTime',
'selectNotify',
(appTime, notify) => {
if (notify.eventId === 'FETCH_FINISHED' && notify.show && appTime - notify.lastSuccess > 3000) {
return { type: 'NOTIFY_DISMISSED' }
}
}
)
}

export default notify
Loading

0 comments on commit 3847f78

Please sign in to comment.