diff --git a/app/components/Network/CanvasNetworkGraph.css b/app/components/Network/CanvasNetworkGraph.css
deleted file mode 100644
index fe0f334b..00000000
--- a/app/components/Network/CanvasNetworkGraph.css
+++ /dev/null
@@ -1,22 +0,0 @@
-.network {
- width: 100%;
- height: 100vh;
- animation: fadein 0.5s;
- animation-timing-function:linear;
- animation-fill-mode: forwards;
- animation-iteration-count: 1;
-}
-
-.links line {
- stroke: #999;
- stroke-opacity: 0.6;
-}
-
-.nodes circle {
- stroke: black ;
- stroke-width: 0px;
-}
-
-.active-peer {
- fill: pink;
-}
\ No newline at end of file
diff --git a/app/components/Network/CanvasNetworkGraph.js b/app/components/Network/CanvasNetworkGraph.js
index d37dd249..10372c44 100644
--- a/app/components/Network/CanvasNetworkGraph.js
+++ b/app/components/Network/CanvasNetworkGraph.js
@@ -2,7 +2,7 @@ import { findDOMNode } from 'react-dom'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import * as d3 from 'd3'
-// import './CanvasNetworkGraph.css'
+import styles from './CanvasNetworkGraph.scss'
function generateSimulationData(nodes, edges) {
const resNodes = nodes.map(node => Object.assign(node, { id: node.pub_key }))
@@ -26,7 +26,9 @@ class CanvasNetworkGraph extends Component {
simulationData: {
nodes: [],
links: []
- }
+ },
+
+ svgLoaded: false
}
this._startSimulation = this._startSimulation.bind(this)
@@ -35,10 +37,31 @@ class CanvasNetworkGraph extends Component {
this._restart = this._restart.bind(this)
}
+ componentWillReceiveProps(nextProps) {
+ const { network } = nextProps
+ const { simulationData: { nodes, links } } = this.state
+
+ const simulationDataEmpty = !nodes.length && !links.length
+ const networkDataLoaded = network.nodes.length || network.edges.length
+
+ // if the simulationData is empty and we have data
+ if (simulationDataEmpty && networkDataLoaded) {
+ this.setState({
+ simulationData: generateSimulationData(network.nodes, network.edges)
+ })
+ }
+ }
+
componentDidMount() {
// wait for the svg to me in the DOM before we start the simulation
const svgInterval = setInterval(() => {
- if (document.getElementById('map')) {
+ if (document.getElementById('mapContainer')) {
+ d3.select('#mapContainer')
+ .append('svg')
+ .attr('id', 'map')
+ .attr('width', 800)
+ .attr('height', 800)
+
this._startSimulation()
clearInterval(svgInterval)
@@ -79,7 +102,6 @@ class CanvasNetworkGraph extends Component {
componentWillUnmount() {
d3.select('#map')
- .selectAll('*')
.remove()
}
@@ -177,6 +199,10 @@ class CanvasNetworkGraph extends Component {
.force('link', d3.forceLink(links).id(d => d.pub_key).distance(500))
.force('collide', d3.forceCollide(300))
.on('tick', this._ticked)
+ .on('end', () => {
+ this.setState({ svgLoaded: true })
+ })
+
// zoom
const zoom_handler = d3.zoom().on('zoom', this._zoomActions)
@@ -235,18 +261,22 @@ class CanvasNetworkGraph extends Component {
}
render() {
- const { simulationData } = this.state
- const {
- network: { nodes, edges, selectedChannel, networkLoading },
- selectedPeerPubkeys,
- selectedChannelIds,
- currentRouteChanIds,
- identity_pubkey
- } = this.props
+ const { svgLoaded } = this.state
return (
-
-
+
+ {
+ !svgLoaded &&
+
+ }
)
}
diff --git a/app/components/Network/CanvasNetworkGraph.scss b/app/components/Network/CanvasNetworkGraph.scss
new file mode 100644
index 00000000..7a9d1da9
--- /dev/null
+++ b/app/components/Network/CanvasNetworkGraph.scss
@@ -0,0 +1,156 @@
+@import '../../variables.scss';
+
+@keyframes fadein {
+ 0% { background: $white; }
+ 50% { background: lighten($secondary, 50%); }
+ 100% { background: $secondary; animation-fill-mode:forwards; }
+}
+
+.mapContainer {
+ position: relative;
+ display: inline-block;
+ width: 70%;
+ height: 100%;
+}
+
+.loadingContainer {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: $secondary;
+}
+
+.loadingWrap {
+ position: relative;
+ top: calc(50% - 150px);
+ width: 150px;
+ margin: 0 auto;
+}
+
+.loader {
+ position: absolute;
+ top: 0;
+ z-index: 10;
+ width: 50px;
+ height: 50px;
+ border: 15px solid;
+ border-radius: 50%;
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+ animation: loadEr 3s infinite;
+}
+
+@keyframes loadEr {
+ 0% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+
+ }
+ 10.4% {
+ border-top-color: rgba(44,44,44,0.5);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+ }
+ 20.8% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+ }
+31.2% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0.5);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+}
+41.6% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+ transform: rotate(40deg);
+}
+52% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0.5);
+ border-left-color: rgba(33,33,33,0);
+}
+62.4% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0);
+}
+72.8% {
+ border-top-color: rgba(44,44,44,0);
+ border-right-color: rgba(55,55,55,0);
+ border-bottom-color: rgba(66,66,66,0);
+ border-left-color: rgba(33,33,33,0.5);
+}
+}
+
+.loaderbefore {
+ width: 50px;
+ height:50px;
+ border: 15px solid #ddd;
+ border-radius: 50%;
+ position: absolute;
+ top: 0;
+ z-index: 9;
+}
+
+.circular {
+ position: absolute;
+ top: -15px;
+ left: -15px;
+ width: 70px;
+ height: 70px;
+ border: 20px solid;
+ border-radius: 50%;
+ border-top-color: #333;
+ border-left-color: #fff;
+ border-bottom-color: #333;
+ border-right-color: #fff;
+ opacity: 0.2;
+ animation: poof 5s infinite;
+}
+@keyframes poof {
+ 0% {transform: scale(1,1) rotate(0deg); opacity: 0.2;}
+ 50% {transform: scale(4,4) rotate(360deg); opacity: 0;}
+}
+.another {
+ opacity: 0.1;
+ transform: rotate(90deg);
+ animation: poofity 5s infinite;
+ animation-delay: 1s;
+}
+@keyframes poofity {
+ 0% {transform: scale(1,1) rotate(90deg); opacity: 0.1;}
+ 50% {transform: scale(4,4) rotate(-360deg); opacity: 0;}
+}
+
+.text {
+ position: absolute;
+ top: 95px;
+ left: 8px;
+ font-family: Arial;
+ text-transform: uppercase;
+ color: #888;
+ animation: opaa 10s infinite;
+}
+@keyframes opaa {
+ 0% {opacity: 1;}
+10% {opacity: 0.5}
+15% {opacity: 1;}
+30% {opacity: 1;}
+65% {opacity: 0.3;}
+90% {opacity: 0.8;}
+}
\ No newline at end of file
diff --git a/app/reducers/network.js b/app/reducers/network.js
index 04f5118e..07680b57 100644
--- a/app/reducers/network.js
+++ b/app/reducers/network.js
@@ -23,8 +23,10 @@ export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ'
export const RESET_PAY_REQ = 'RESET_PAY_REQ'
export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS'
+export const CLEAR_SELECTED_PEERS = 'CLEAR_SELECTED_PEERS'
export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS'
+export const CLEAR_SELECTED_CHANNELS = 'CLEAR_SELECTED_CHANNELS'
export const GET_INFO_AND_QUERY_ROUTES = 'GET_INFO_AND_QUERY_ROUTES'
export const RECEIVE_INFO_AND_QUERY_ROUTES = 'RECEIVE_INFO_AND_QUERY_ROUTES'
@@ -113,6 +115,18 @@ export function clearQueryRoutes() {
}
}
+export function clearSelectedPeers() {
+ return {
+ type: CLEAR_SELECTED_PEERS
+ }
+}
+
+export function clearSelectedChannels() {
+ return {
+ type: CLEAR_SELECTED_CHANNELS
+ }
+}
+
// Send IPC event for describeNetwork
export const fetchDescribeNetwork = () => (dispatch) => {
dispatch(getDescribeNetwork())
@@ -185,6 +199,7 @@ const ACTION_HANDLERS = {
...state, selectedPeers
}
},
+ [CLEAR_SELECTED_PEERS]: state => ({ ...state, selectedPeers: [] }),
[UPDATE_SELECTED_CHANNELS]: (state, { channel }) => {
let selectedChannels
@@ -200,7 +215,8 @@ const ACTION_HANDLERS = {
return {
...state, selectedChannels
}
- }
+ },
+ [CLEAR_SELECTED_CHANNELS]: state => ({ ...state, selectedChannels: [] }),
}
// ------------------------------------
diff --git a/app/routes/network/components/Network.js b/app/routes/network/components/Network.js
index 60efa0c4..921315cf 100644
--- a/app/routes/network/components/Network.js
+++ b/app/routes/network/components/Network.js
@@ -34,10 +34,12 @@ class Network extends Component {
}
componentWillUnmount() {
- const { clearQueryRoutes, resetPayReq } = this.props
+ const { clearQueryRoutes, resetPayReq, clearSelectedChannels, clearSelectedPeers } = this.props
clearQueryRoutes()
- resetPayReq()
+ resetPayReq()
+ clearSelectedChannels()
+ clearSelectedPeers()
}
render() {
diff --git a/app/routes/network/containers/NetworkContainer.js b/app/routes/network/containers/NetworkContainer.js
index 85428b70..f78b4592 100644
--- a/app/routes/network/containers/NetworkContainer.js
+++ b/app/routes/network/containers/NetworkContainer.js
@@ -5,8 +5,13 @@ import {
fetchDescribeNetwork,
setCurrentTab,
+
updateSelectedPeers,
+ clearSelectedPeers,
+
updateSelectedChannels,
+ clearSelectedChannels,
+
setCurrentRoute,
updatePayReq,
@@ -25,7 +30,10 @@ import Network from '../components/Network'
const mapDispatchToProps = {
fetchDescribeNetwork,
setCurrentTab,
+
updateSelectedPeers,
+ clearSelectedPeers,
+
updatePayReq,
fetchInvoiceAndQueryRoutes,
setCurrentRoute,
@@ -35,7 +43,8 @@ const mapDispatchToProps = {
fetchPeers,
fetchChannels,
- updateSelectedChannels
+ updateSelectedChannels,
+ clearSelectedChannels
}
const mapStateToProps = state => ({