Browse Source

fix(old code): remove old v1 stuff

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
e9d7a46ceb
  1. 38
      app/components/Contacts/ClosingContact.js
  2. 156
      app/components/Contacts/Contact.scss
  3. 35
      app/components/Contacts/LoadingContact.js
  4. 34
      app/components/Contacts/OfflineContact.js
  5. 34
      app/components/Contacts/OnlineContact.js
  6. 0
      app/components/Contacts/OnlineContact.scss
  7. 38
      app/components/Contacts/PendingContact.js
  8. 274
      app/components/Network/CanvasNetworkGraph.js
  9. 156
      app/components/Network/CanvasNetworkGraph.scss
  10. 45
      app/components/Network/ChannelsList.js
  11. 78
      app/components/Network/ChannelsList.scss
  12. 25
      app/components/Network/PeersList.js
  13. 46
      app/components/Network/PeersList.scss
  14. 63
      app/components/Network/TransactionForm.js
  15. 125
      app/components/Network/TransactionForm.scss
  16. 6
      app/routes.js
  17. 196
      app/routes/contacts/components/Contacts.js
  18. 172
      app/routes/contacts/components/Contacts.scss
  19. 115
      app/routes/contacts/containers/ContactsContainer.js
  20. 3
      app/routes/contacts/index.js
  21. 88
      app/routes/help/components/Help.js
  22. 90
      app/routes/help/components/Help.scss
  23. 10
      app/routes/help/containers/HelpContainer.js
  24. 3
      app/routes/help/index.js
  25. 168
      app/routes/network/components/Network.js
  26. 99
      app/routes/network/components/Network.scss
  27. 62
      app/routes/network/containers/NetworkContainer.js
  28. 3
      app/routes/network/index.js

38
app/components/Contacts/ClosingContact.js

@ -1,38 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import { btc, blockExplorer } from 'utils'
import styles from './Contact.scss'
const ClosingContact = ({ channel }) => (
<li className={styles.friend}>
<section className={styles.info}>
<p className={styles.closing}>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>
Removing
<i onClick={() => blockExplorer.showChannelClosing(channel)}>
(Details)
</i>
</span>
</p>
<h2>{channel.channel.remote_node_pub}</h2>
</section>
<section className={styles.limits}>
<div>
<h4>Can Pay</h4>
<p>{btc.satoshisToBtc(channel.channel.local_balance)}BTC</p>
</div>
<div>
<h4>Can Receive</h4>
<p>{btc.satoshisToBtc(channel.channel.remote_balance)}BTC</p>
</div>
</section>
</li>
)
ClosingContact.propTypes = {
channel: PropTypes.object.isRequired
}
export default ClosingContact

156
app/components/Contacts/Contact.scss

@ -1,156 +0,0 @@
@import '../../variables.scss';
.friend {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 30px 60px 60px 60px;
cursor: pointer;
transition: all 0.25s;
&.loading {
.info {
opacity: 0.2;
}
}
&:hover {
background: $lightgrey;
}
.limits {
display: flex;
flex-direction: row;
justify-content: space-between;
div {
margin: 0 10px;
h4 {
font-size: 12px;
margin-bottom: 20px;
}
}
}
.info {
p {
margin-bottom: 20px;
&.online {
color: $green;
svg {
color: $green;
}
}
&.pending {
color: $orange;
svg {
color: $orange;
}
i {
margin-left: 5px;
color: $darkestgrey;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
&.closing {
color: $red;
svg {
color: $red;
}
i {
margin-left: 5px;
color: $darkestgrey;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
svg, span {
display: inline-block;
vertical-align: top;
}
svg {
margin-right: 5px;
width: 12px;
height: 12px;
color: $darkestgrey;
}
span {
font-size: 12px;
}
}
h2 {
color: $black;
font-size: 14px;
font-weight: bold;
letter-spacing: 1.3px;
span {
color: $darkestgrey;
margin-left: 5px;
}
}
}
}
@-webkit-keyframes animation-rotate {
100% {
-webkit-transform: rotate(360deg);
}
}
@-moz-keyframes animation-rotate {
100% {
-moz-transform: rotate(360deg);
}
}
@-o-keyframes animation-rotate {
100% {
-o-transform: rotate(360deg);
}
}
@keyframes animation-rotate {
100% {
transform: rotate(360deg);
}
}
.spinner {
border: 1px solid rgba(0, 0, 0, 0.1);
border-left-color: rgba(0, 0, 0, 0.4);
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
border-radius: 999px;
}
.spinner {
margin: 0 auto;
height: 50px;
width: 50px;
-webkit-animation: animation-rotate 1000ms linear infinite;
-moz-animation: animation-rotate 1000ms linear infinite;
-o-animation: animation-rotate 1000ms linear infinite;
animation: animation-rotate 1000ms linear infinite;
}

35
app/components/Contacts/LoadingContact.js

@ -1,35 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import styles from './Contact.scss'
const LoadingContact = ({ pubkey, isClosing }) => (
<li className={`${styles.friend} ${styles.loading}`}>
<section className={styles.info}>
<p>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>
{
isClosing ?
'Closing'
:
'Loading'
}
</span>
</p>
<h2>{pubkey}</h2>
</section>
<section className={styles.limits}>
<div className={styles.loading}>
<div className={styles.spinner} />
</div>
</section>
</li>
)
LoadingContact.propTypes = {
pubkey: PropTypes.string.isRequired,
isClosing: PropTypes.bool.isRequired
}
export default LoadingContact

34
app/components/Contacts/OfflineContact.js

@ -1,34 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import { btc } from 'utils'
import styles from './Contact.scss'
const OfflineContact = ({ channel, openContactModal }) => (
<li className={styles.friend} key={channel.chan_id} onClick={() => openContactModal(channel)}>
<section className={styles.info}>
<p>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>Offline</span>
</p>
<h2>{channel.remote_pubkey}</h2>
</section>
<section className={styles.limits}>
<div>
<h4>Can Pay</h4>
<p>{btc.satoshisToBtc(channel.local_balance)}BTC</p>
</div>
<div>
<h4>Can Receive</h4>
<p>{btc.satoshisToBtc(channel.remote_balance)}BTC</p>
</div>
</section>
</li>
)
OfflineContact.propTypes = {
channel: PropTypes.object.isRequired,
openContactModal: PropTypes.func.isRequired
}
export default OfflineContact

34
app/components/Contacts/OnlineContact.js

@ -1,34 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import { btc } from 'utils'
import styles from './Contact.scss'
const OnlineContact = ({ channel, openContactModal }) => (
<li className={styles.friend} key={channel.chan_id} onClick={() => openContactModal(channel)}>
<section className={styles.info}>
<p className={styles.online}>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>Online</span>
</p>
<h2>{channel.remote_pubkey}</h2>
</section>
<section className={styles.limits}>
<div>
<h4>Can Pay</h4>
<p>{btc.satoshisToBtc(channel.local_balance)}BTC</p>
</div>
<div>
<h4>Can Receive</h4>
<p>{btc.satoshisToBtc(channel.remote_balance)}BTC</p>
</div>
</section>
</li>
)
OnlineContact.propTypes = {
channel: PropTypes.object.isRequired,
openContactModal: PropTypes.func.isRequired
}
export default OnlineContact

0
app/components/Contacts/OnlineContact.scss

38
app/components/Contacts/PendingContact.js

@ -1,38 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import { btc, blockExplorer } from 'utils'
import styles from './Contact.scss'
const PendingContact = ({ channel }) => (
<li className={styles.friend} key={channel.chan_id}>
<section className={styles.info}>
<p className={styles.pending}>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>
Pending
<i onClick={() => blockExplorer.showChannelPoint(channel)}>
(Details)
</i>
</span>
</p>
<h2>{channel.channel.remote_node_pub}</h2>
</section>
<section className={styles.limits}>
<div>
<h4>Can Pay</h4>
<p>{btc.satoshisToBtc(channel.channel.local_balance)}BTC</p>
</div>
<div>
<h4>Can Receive</h4>
<p>{btc.satoshisToBtc(channel.channel.remote_balance)}BTC</p>
</div>
</section>
</li>
)
PendingContact.propTypes = {
channel: PropTypes.object.isRequired
}
export default PendingContact

274
app/components/Network/CanvasNetworkGraph.js

@ -1,274 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import * as d3Force from 'd3-force'
import * as d3Selection from 'd3-selection'
import * as d3Zoom from 'd3-zoom'
import styles from './CanvasNetworkGraph.scss'
const d3 = Object.assign({}, d3Force, d3Selection, d3Zoom)
function generateSimulationData(nodes, edges) {
const resNodes = nodes.map(node => Object.assign(node, { id: node.pub_key }))
const resEdges = edges.map(node => Object.assign(node, { source: node.node1_pub, target: node.node2_pub }))
return {
nodes: resNodes,
links: resEdges
}
}
class CanvasNetworkGraph extends Component {
constructor(props) {
super(props)
this.state = {
simulationData: {
nodes: [],
links: []
},
svgLoaded: false
}
this.startSimulation = this.startSimulation.bind(this)
this.zoomActions = this.zoomActions.bind(this)
this.ticked = this.ticked.bind(this)
this.restart = this.restart.bind(this)
}
componentDidMount() {
// wait for the svg to be in the DOM before we start the simulation
const svgInterval = setInterval(() => {
if (document.getElementById('mapContainer')) {
d3.select('#mapContainer')
.append('svg')
.attr('id', 'map')
.attr('width', '100%')
.attr('height', '100%')
this.startSimulation()
clearInterval(svgInterval)
}
}, 1000)
}
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
const prevNetwork = this.props.network
if (
// update the simulationData only if
// the simulationData is empty and we have network data
(simulationDataEmpty && networkDataLoaded) ||
// the nodes or edges have changed
(prevNetwork.nodes.length !== network.nodes.length || prevNetwork.edges.length !== network.edges.length)) {
this.setState({
simulationData: generateSimulationData(network.nodes, network.edges)
})
}
}
componentDidUpdate(prevProps) {
const {
selectedPeerPubkeys,
selectedChannelIds,
currentRouteChanIds
} = this.props
if (prevProps.selectedPeerPubkeys.length !== selectedPeerPubkeys.length) {
this.updateSelectedPeers()
}
if (prevProps.selectedChannelIds.length !== selectedChannelIds.length) {
this.updateSelectedChannels()
}
if (prevProps.currentRouteChanIds.length !== currentRouteChanIds.length) {
this.renderSelectedRoute()
}
}
componentWillUnmount() {
d3.select('#map')
.remove()
}
updateSelectedPeers() {
const { selectedPeerPubkeys } = this.props
// remove active class
d3.selectAll('.active-peer').classed('active-peer', false)
// add active class to all selected peers
selectedPeerPubkeys.forEach((pubkey) => {
d3.select(`#node-${pubkey}`).classed('active-peer', true)
})
}
updateSelectedChannels() {
const { selectedChannelIds } = this.props
// remove active class
d3.selectAll('.active-channel').classed('active-channel', false)
// add active class to all selected peers
selectedChannelIds.forEach((chanid) => {
d3.select(`#link-${chanid}`).classed('active-channel', true)
})
}
startSimulation() {
const { simulationData: { nodes, links } } = this.state
// grab the svg el along with the attributes
const svg = d3.select('#map')
const svgBox = svg.node().getBBox()
this.g = svg.append('g').attr('transform', `translate(${svgBox.width / 2},${svgBox.height / 2})`)
this.link = this.g.append('g').attr('stroke', 'white').attr('stroke-width', 1.5).selectAll('.link')
this.node = this.g.append('g').attr('stroke', 'silver').attr('stroke-width', 1.5).selectAll('.node')
this.simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody().strength(-750))
.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)
zoom_handler(svg)
this.restart()
}
zoomActions() {
this.g.attr('transform', d3Selection.event.transform)
}
ticked() {
this.node.attr('cx', d => d.x)
.attr('cy', d => d.y)
this.link.attr('x1', d => d.source.x)
.attr('y1', d => d.source.y)
.attr('x2', d => d.target.x)
.attr('y2', d => d.target.y)
}
restart() {
const { identity_pubkey } = this.props
const { simulationData: { nodes, links } } = this.state
// Apply the general update pattern to the nodes.
this.node = this.node.data(nodes, d => d.pub_key)
this.node.exit().remove()
this.node = this.node.enter()
.append('circle')
.attr('stroke', () => 'silver')
.attr('fill', d => (d.pub_key === identity_pubkey ? '#FFF' : '#353535'))
.attr('r', () => 100)
.attr('id', d => `node-${d.pub_key}`)
.attr('class', 'network-node')
.merge(this.node)
// Apply the general update pattern to the links.
this.link = this.link.data(links, d => `${d.source.id}-${d.target.id}`)
this.link.exit().remove()
this.link =
this.link.enter()
.append('line')
.attr('id', d => `link-${d.channel_id}`)
.attr('class', 'network-link')
.merge(this.link)
// Update and restart the simulation.
this.simulation.nodes(nodes)
this.simulation.force('link').links(links)
this.simulation.restart()
}
renderSelectedRoute() {
const { currentRouteChanIds } = this.props
// remove all route animations before rendering new ones
d3.selectAll('.animated-route-circle').remove()
currentRouteChanIds.forEach((chanId) => {
const link = document.getElementById(`link-${chanId}`)
if (!link) { return }
const x1 = link.x1.baseVal.value
const x2 = link.x2.baseVal.value
const y1 = link.y1.baseVal.value
const y2 = link.y2.baseVal.value
// create the circle that represent btc traveling through a channel
this.g
.append('circle')
.attr('id', `circle-${chanId}`)
.attr('class', 'animated-route-circle')
.attr('r', 50)
.attr('cx', x1)
.attr('cy', y1)
.attr('fill', '#FFDC53')
// we want the animation to repeat back and forth, this function executes that visually
const repeat = () => {
d3.select(`#circle-${chanId}`)
.transition()
.attr('cx', x2)
.attr('cy', y2)
.duration(1000)
.transition()
.duration(1000)
.attr('cx', x1)
.attr('cy', y1)
.on('end', repeat)
}
// call repeat to animate the circle
repeat()
})
}
render() {
const { svgLoaded } = this.state
return (
<div className={styles.mapContainer} id='mapContainer'>
{
!svgLoaded &&
<div className={styles.loadingContainer}>
<div className={styles.loadingWrap}>
<div className={styles.loader} />
<div className={styles.loaderbefore} />
<div className={styles.circular} />
<div className={`${styles.circular} ${styles.another}`} />
<div className={styles.text}>loading</div>
</div>
</div>
}
</div>
)
}
}
CanvasNetworkGraph.propTypes = {
identity_pubkey: PropTypes.string.isRequired,
network: PropTypes.object.isRequired,
selectedPeerPubkeys: PropTypes.array.isRequired,
selectedChannelIds: PropTypes.array.isRequired,
currentRouteChanIds: PropTypes.array.isRequired
}
export default CanvasNetworkGraph

156
app/components/Network/CanvasNetworkGraph.scss

@ -1,156 +0,0 @@
@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;}
}

45
app/components/Network/ChannelsList.js

@ -1,45 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { btc, blockExplorer } from 'utils'
import styles from './ChannelsList.scss'
const ChannelsList = ({ channels, updateSelectedChannels, selectedChannelIds }) => (
<ul className={styles.channels}>
{
channels.map(channel => (
<li key={channel.chan_id} className={styles.channel} onClick={() => updateSelectedChannels(channel)}>
<span className={`${styles.dot} ${selectedChannelIds.includes(channel.chan_id) && styles.active}`} />
<header>
<h1>Capacity: {btc.satoshisToBtc(channel.capacity)}</h1>
<span onClick={() => blockExplorer.showChannelPoint({ channel })}>Channel Point</span>
</header>
<section>
<h4>Remote Pubkey:</h4>
<p>{channel.remote_pubkey.substring(0, Math.min(30, channel.remote_pubkey.length))}...</p>
</section>
<section className={styles.funds}>
<div>
<h4>Sent:</h4>
<p>{btc.satoshisToBtc(channel.total_satoshis_sent)} BTC</p>
</div>
<div>
<h4>Received:</h4>
<p>{btc.satoshisToBtc(channel.total_satoshis_received)} BTC</p>
</div>
</section>
</li>
))
}
</ul>
)
ChannelsList.propTypes = {
channels: PropTypes.array.isRequired,
updateSelectedChannels: PropTypes.func.isRequired,
selectedChannelIds: PropTypes.array.isRequired
}
export default ChannelsList

78
app/components/Network/ChannelsList.scss

@ -1,78 +0,0 @@
@import '../../variables.scss';
.channels {
color: $white;
margin-top: 50px;
}
.channel {
position: relative;
margin: 20px 0;
padding: 10px 40px;
cursor: pointer;
transition: all 0.25s;
&:hover {
background: darken(#353535, 10%);
.dot {
background: #88D4A2;
opacity: 0.5;
}
}
.dot {
position: absolute;
top: calc(15% - 10px);
left: 5%;
width: 10px;
height: 10px;
border: 1px solid #979797;
border-radius: 50%;
&.active {
background: #88D4A2;
}
}
header {
margin-bottom: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
h1 {
margin-bottom: 10px;
}
span {
font-size: 10px;
text-decoration: underline;
transition: all 0.25s;
&:hover {
color: #88D4A2;
}
}
}
section {
margin: 10px 0;
h4 {
font-weight: bold;
text-transform: uppercase;
font-size: 10px;
margin-bottom: 5px;
}
}
.funds {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: 20px;
}
}

25
app/components/Network/PeersList.js

@ -1,25 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import styles from './PeersList.scss'
const PeersList = ({ peers, updateSelectedPeers, selectedPeerPubkeys }) => (
<ul className={styles.peers}>
{
peers.map(peer => (
<li key={peer.peer_id} className={styles.peer} onClick={() => updateSelectedPeers(peer)}>
<span className={`${styles.dot} ${selectedPeerPubkeys.includes(peer.pub_key) && styles.active}`} />
<h1>{peer.address}</h1>
<h4>{peer.pub_key}</h4>
</li>
))
}
</ul>
)
PeersList.propTypes = {
peers: PropTypes.array.isRequired,
updateSelectedPeers: PropTypes.func.isRequired,
selectedPeerPubkeys: PropTypes.array.isRequired
}
export default PeersList

46
app/components/Network/PeersList.scss

@ -1,46 +0,0 @@
@import '../../variables.scss';
.peers {
color: $white;
margin-top: 50px;
}
.peer {
position: relative;
margin: 20px 0;
padding: 10px 40px;
cursor: pointer;
transition: all 0.25s;
&:hover {
background: darken(#353535, 10%);
.dot {
background: #5589F3;
opacity: 0.5;
}
}
.dot {
position: absolute;
top: calc(50% - 10px);
left: 5%;
width: 10px;
height: 10px;
border: 1px solid #979797;
border-radius: 50%;
&.active {
background: #5589F3;
}
}
h1 {
font-size: 16px;
margin-bottom: 10px;
}
h4 {
font-size: 8px;
}
}

63
app/components/Network/TransactionForm.js

@ -1,63 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { btc } from 'utils'
import styles from './TransactionForm.scss'
const TransactionForm = ({
updatePayReq, pay_req, loadingRoutes, payReqRoutes, setCurrentRoute, currentRoute
}) => (
<div className={styles.transactionForm}>
<div className={styles.form}>
<input
className={styles.transactionInput}
placeholder='Payment request...'
value={pay_req}
onChange={event => updatePayReq(event.target.value)}
/>
</div>
{
loadingRoutes &&
<div className={styles.loading}>
<div className={styles.spinner} />
<h1>calculating all routes...</h1>
</div>
}
<ul className={styles.routes}>
{
payReqRoutes.map((route, index) => (
<li className={`${styles.route} ${currentRoute === route && styles.active}`} key={index} onClick={() => setCurrentRoute(route)}>
<header>
<h1>Route #{index + 1}</h1>
<span>Hops: {route.hops.length}</span>
</header>
<div className={styles.data}>
<section>
<h4>Amount</h4>
<span>{btc.satoshisToBtc(route.total_amt)} BTC</span>
</section>
<section>
<h4>Fees</h4>
<span>{btc.satoshisToBtc(route.total_fees)} BTC</span>
</section>
</div>
</li>
))
}
</ul>
</div>
)
TransactionForm.propTypes = {
updatePayReq: PropTypes.func.isRequired,
pay_req: PropTypes.string.isRequired,
loadingRoutes: PropTypes.bool.isRequired,
payReqRoutes: PropTypes.array.isRequired,
setCurrentRoute: PropTypes.func.isRequired,
currentRoute: PropTypes.object.isRequired
}
export default TransactionForm

125
app/components/Network/TransactionForm.scss

@ -1,125 +0,0 @@
@import '../../variables.scss';
@-webkit-keyframes animation-rotate {
100% {
-webkit-transform: rotate(360deg);
}
}
@-moz-keyframes animation-rotate {
100% {
-moz-transform: rotate(360deg);
}
}
@-o-keyframes animation-rotate {
100% {
-o-transform: rotate(360deg);
}
}
@keyframes animation-rotate {
100% {
transform: rotate(360deg);
}
}
.spinner {
border: 1px solid rgba(255, 220, 83, 0.1);
border-left-color: rgba(255, 220, 83, 0.4);
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
border-radius: 999px;
}
.spinner {
margin: 0 auto;
height: 100px;
width: 100px;
-webkit-animation: animation-rotate 1000ms linear infinite;
-moz-animation: animation-rotate 1000ms linear infinite;
-o-animation: animation-rotate 1000ms linear infinite;
animation: animation-rotate 1000ms linear infinite;
}
.loading {
margin-top: 40px;
h1 {
text-align: center;
margin-top: 25px;
}
}
.transactionForm {
color: $white;
margin-top: 50px;
.form {
padding: 0 20px;
}
.transactionInput {
outline: 0;
border: 0;
border-bottom: 1px solid $secondary;
color: $secondary;
background: transparent;
padding: 5px;
width: 100%;
font-size: 14px;
color: $white;
}
}
.routes {
margin-top: 40px;
}
.route {
margin: 20px 0;
padding: 20px;
cursor: pointer;
&:hover {
background: darken(#353535, 10%);
}
&.active {
background: darken(#353535, 10%);
}
header {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 20px;
h1 {
font-size: 16px;
font-weight: bold;
}
span {
font-weight: bold;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 1.2px;
}
}
.data {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
section {
h4 {
font-size: 12px;
font-weight: bold;
margin-bottom: 5px;
}
}
}
}

6
app/routes.js

@ -3,16 +3,10 @@ import React from 'react'
import { Switch, Route } from 'react-router'
import App from './routes/app'
import Activity from './routes/activity'
import Contacts from './routes/contacts'
import Network from './routes/network'
import Help from './routes/help'
const routes = () => (
<App>
<Switch>
<Route path='/contacts' component={Contacts} />
<Route path='/network' component={Network} />
<Route path='/help' component={Help} />
<Route path='/' component={Activity} />
</Switch>
</App>

196
app/routes/contacts/components/Contacts.js

@ -1,196 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Isvg from 'react-inlinesvg'
import { MdSearch } from 'react-icons/lib/md'
import { FaAngleDown, FaRepeat } from 'react-icons/lib/fa'
import ContactModal from 'components/Contacts/ContactModal'
import ContactsForm from 'components/Contacts/ContactsForm'
import OnlineContact from 'components/Contacts/OnlineContact'
import PendingContact from 'components/Contacts/PendingContact'
import ClosingContact from 'components/Contacts/ClosingContact'
import OfflineContact from 'components/Contacts/OfflineContact'
import LoadingContact from 'components/Contacts/LoadingContact'
import plus from 'icons/plus.svg'
import styles from './Contacts.scss'
class Contacts extends Component {
constructor(props) {
super(props)
this.state = {
refreshing: false
}
}
componentWillMount() {
const { fetchChannels, fetchPeers, fetchDescribeNetwork } = this.props
fetchChannels()
fetchPeers()
fetchDescribeNetwork()
}
render() {
const {
channels: {
searchQuery,
filterPulldown,
filter,
loadingChannelPubkeys,
closingChannelIds
},
currentChannels,
activeChannels,
fetchChannels,
updateChannelSearchQuery,
toggleFilterPulldown,
changeFilter,
nonActiveFilters,
openContactsForm,
openContactModal,
contactModalProps,
contactsFormProps
} = this.props
console.log('currentChannels: ', currentChannels)
const refreshClicked = () => {
// turn the spinner on
this.setState({ refreshing: true })
// store event in icon so we dont get an error when react clears it
const icon = this.repeat.childNodes
// fetch channels
fetchChannels()
// wait for the svg to appear as child
const svgTimeout = setTimeout(() => {
if (icon[0].tagName === 'svg') {
// spin icon for 1 sec
icon[0].style.animation = 'spin 1000ms linear 1'
clearTimeout(svgTimeout)
}
}, 1)
// clear animation after the second so we can reuse it
const refreshTimeout = setTimeout(() => {
icon[0].style.animation = ''
this.setState({ refreshing: false })
clearTimeout(refreshTimeout)
}, 1000)
}
return (
<div className={styles.friendsContainer}>
<ContactModal {...contactModalProps} />
<ContactsForm {...contactsFormProps} />
<header className={styles.header}>
<div className={styles.titleContainer}>
<div className={styles.left}>
<h1>Contacts <span>({activeChannels.length} online)</span></h1>
</div>
</div>
<div className={styles.newFriendContainer}>
<div className={`buttonPrimary ${styles.newFriendButton}`} onClick={openContactsForm}>
<Isvg src={plus} />
<span>Add</span>
</div>
</div>
</header>
<div className={styles.search}>
<label className={`${styles.label} ${styles.input}`} htmlFor='channelSearch'>
<MdSearch />
</label>
<input
value={searchQuery}
onChange={event => updateChannelSearchQuery(event.target.value)}
className={`${styles.text} ${styles.input}`}
placeholder='Search your contacts list...'
type='text'
id='channelSearch'
/>
</div>
<div className={styles.filtersContainer}>
<section>
<h2 onClick={toggleFilterPulldown} className={styles.filterTitle}>
{filter.name} <span className={filterPulldown && styles.pulldown}><FaAngleDown /></span>
</h2>
<ul className={`${styles.filters} ${filterPulldown && styles.active}`}>
{
nonActiveFilters.map(f => (
<li key={f.key} onClick={() => changeFilter(f)}>
{f.name}
</li>
))
}
</ul>
</section>
<section className={styles.refreshContainer}>
<span className={styles.refresh} onClick={refreshClicked} ref={(ref) => { this.repeat = ref }}>
{
this.state.refreshing ?
<FaRepeat />
:
'Refresh'
}
</span>
</section>
</div>
<ul className={`${styles.friends} ${filterPulldown && styles.fade}`}>
{
loadingChannelPubkeys.map(pubkey => <LoadingContact pubkey={pubkey} isClosing={false} key={pubkey} />)
}
{
currentChannels.length > 0 && currentChannels.map((channel, index) => {
if (closingChannelIds.includes(channel.chan_id)) {
return <LoadingContact pubkey={channel.remote_pubkey} isClosing key={index} />
} else if (Object.prototype.hasOwnProperty.call(channel, 'confirmation_height')) {
return <PendingContact channel={channel} key={index} />
} else if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) {
return <ClosingContact channel={channel} key={index} />
} else if (!channel.active) {
return <OfflineContact channel={channel} key={index} openContactModal={openContactModal} />
}
return <OnlineContact channel={channel} key={index} openContactModal={openContactModal} />
})
}
</ul>
</div>
)
}
}
Contacts.propTypes = {
fetchPeers: PropTypes.func.isRequired,
fetchDescribeNetwork: PropTypes.func.isRequired,
channels: PropTypes.object.isRequired,
currentChannels: PropTypes.array.isRequired,
activeChannels: PropTypes.array.isRequired,
fetchChannels: PropTypes.func.isRequired,
updateChannelSearchQuery: PropTypes.func.isRequired,
toggleFilterPulldown: PropTypes.func.isRequired,
changeFilter: PropTypes.func.isRequired,
nonActiveFilters: PropTypes.array.isRequired,
openContactsForm: PropTypes.func.isRequired,
openContactModal: PropTypes.func.isRequired,
contactModalProps: PropTypes.object.isRequired,
contactsFormProps: PropTypes.object.isRequired
}
export default Contacts

172
app/routes/contacts/components/Contacts.scss

@ -1,172 +0,0 @@
@import '../../../variables.scss';
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
background: $lightgrey;
.titleContainer {
padding: 20px 40px;
.left {
padding: 10px 0;
h1 {
text-transform: uppercase;
font-size: 26px;
margin-right: 5px;
span {
display: inline-block;
vertical-align: middle;
font-size: 16px;
}
}
}
}
.newFriendContainer {
padding: 20px 40px;
.newFriendButton {
box-shadow: none;
transition: all 0.25s;
padding-top: 12px;
padding-bottom: 10px;
font-size: 14px;
&:hover {
background: darken($main, 10%);
}
span {
display: inline-block;
vertical-align: top;
&:nth-child(1) svg {
width: 14px;
height: 14px;
margin-right: 5px;
}
}
}
}
}
.search {
height: 55px;
padding: 2px 25px;
border-top: 1px solid $darkgrey;
border-bottom: 1px solid $darkgrey;
background: $white;
.input {
display: inline-block;
vertical-align: top;
height: 100%;
}
.label {
width: 5%;
line-height: 50px;
font-size: 20px;
text-align: center;
cursor: pointer;
}
.text {
width: 95%;
outline: 0;
padding: 0;
border: 0;
border-radius: 0;
height: 50px;
font-size: 16px;
}
}
.filtersContainer {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20px;
padding: 20px 40px;
h2, h2 span {
color: $bluegrey;
cursor: pointer;
transition: color 0.25s;
&:hover {
color: lighten($bluegrey, 10%);
}
}
h2, .filters li {
text-transform: uppercase;
letter-spacing: 1.5px;
color: $darkestgrey;
font-size: 14px;
font-weight: 400;
}
h2 span.pulldown {
color: $main;
}
.filters {
display: none;
&.active {
display: block;
position: absolute;
bottom: -100px;
z-index: 10;
li {
margin: 5px 0;
cursor: pointer;
&:hover {
color: $main;
}
}
}
}
.refreshContainer {
text-align: right;
cursor: pointer;
.refresh {
cursor: pointer;
color: $darkestgrey;
transition: all 0.25s;
&:hover {
color: $main;
}
svg {
font-size: 12px;
color: $darkestgrey;
&:hover {
color: $darkestgrey;
}
}
}
}
}
.friends {
padding: 10px 0 60px 0;
opacity: 1;
transition: all 0.25s;
&.fade {
opacity: 0.05;
}
}

115
app/routes/contacts/containers/ContactsContainer.js

@ -1,115 +0,0 @@
import { withRouter } from 'react-router'
import { connect } from 'react-redux'
import {
fetchChannels,
openChannel,
closeChannel,
updateChannelSearchQuery,
toggleFilterPulldown,
changeFilter,
openContactModal,
closeContactModal,
currentChannels,
channelsSelectors
} from 'reducers/channels'
import { fetchPeers } from 'reducers/peers'
import { fetchDescribeNetwork } from 'reducers/network'
import {
openContactsForm,
closeContactsForm,
updateContactFormSearchQuery,
updateManualFormSearchQuery,
updateContactCapacity,
contactFormSelectors,
updateManualFormErrors
} from 'reducers/contactsform'
import Contacts from '../components/Contacts'
const mapDispatchToProps = {
openContactsForm,
closeContactsForm,
openContactModal,
closeContactModal,
updateContactFormSearchQuery,
updateManualFormSearchQuery,
updateContactCapacity,
openChannel,
closeChannel,
updateChannelSearchQuery,
toggleFilterPulldown,
changeFilter,
updateManualFormErrors,
fetchChannels,
fetchPeers,
fetchDescribeNetwork
}
const mapStateToProps = state => ({
channels: state.channels,
peers: state.peers,
network: state.network,
contactsform: state.contactsform,
currentChannels: currentChannels(state),
activeChannels: channelsSelectors.activeChannels(state),
activeChannelPubkeys: channelsSelectors.activeChannelPubkeys(state),
nonActiveChannels: channelsSelectors.nonActiveChannels(state),
nonActiveChannelPubkeys: channelsSelectors.nonActiveChannelPubkeys(state),
pendingOpenChannels: channelsSelectors.pendingOpenChannels(state),
pendingOpenChannelPubkeys: channelsSelectors.pendingOpenChannelPubkeys(state),
closingPendingChannels: channelsSelectors.closingPendingChannels(state),
nonActiveFilters: channelsSelectors.nonActiveFilters(state),
channelNodes: channelsSelectors.channelNodes(state),
filteredNetworkNodes: contactFormSelectors.filteredNetworkNodes(state),
showManualForm: contactFormSelectors.showManualForm(state),
manualFormIsValid: contactFormSelectors.manualFormIsValid(state)
})
const mergeProps = (stateProps, dispatchProps, ownProps) => {
const contactModalProps = {
closeContactModal: dispatchProps.closeContactModal,
closeChannel: dispatchProps.closeChannel,
isOpen: stateProps.channels.contactModal.isOpen,
channel: stateProps.channels.contactModal.channel,
channelNodes: stateProps.channelNodes,
closingChannelIds: stateProps.channels.closingChannelIds,
manualFormIsValid: stateProps.manualFormIsValid
}
const contactsFormProps = {
closeContactsForm: dispatchProps.closeContactsForm,
updateContactFormSearchQuery: dispatchProps.updateContactFormSearchQuery,
updateManualFormSearchQuery: dispatchProps.updateManualFormSearchQuery,
updateContactCapacity: dispatchProps.updateContactCapacity,
openChannel: dispatchProps.openChannel,
contactsform: stateProps.contactsform,
filteredNetworkNodes: stateProps.filteredNetworkNodes,
loadingChannelPubkeys: stateProps.channels.loadingChannelPubkeys,
showManualForm: stateProps.showManualForm,
manualFormIsValid: stateProps.manualFormIsValid,
activeChannelPubkeys: stateProps.activeChannelPubkeys,
nonActiveChannelPubkeys: stateProps.nonActiveChannelPubkeys,
pendingOpenChannelPubkeys: stateProps.pendingOpenChannelPubkeys,
updateManualFormErrors: dispatchProps.updateManualFormErrors
}
return {
...stateProps,
...dispatchProps,
...ownProps,
contactModalProps,
contactsFormProps
}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps, mergeProps)(Contacts))

3
app/routes/contacts/index.js

@ -1,3 +0,0 @@
import ContactsContainer from './containers/ContactsContainer'
export default ContactsContainer

88
app/routes/help/components/Help.js

@ -1,88 +0,0 @@
import { shell } from 'electron'
import React, { Component } from 'react'
import { MdSearch } from 'react-icons/lib/md'
import styles from './Help.scss'
class Help extends Component {
constructor(props) {
super(props)
this.state = {
videos: [
{
id: '8kZq6eec49A',
title: 'Syncing and Depositing - Zap Lightning Network Wallet Tutorial (Video 1)'
},
{
id: 'xSiTH63fOQM',
title: 'Adding a contact - Zap Lightning Network Wallet Tutorial (Video 2)'
},
{
id: 'c0SLmywYDHU',
title: 'Making a Lightning Network payment - Zap Lightning Network Wallet Tutorial (Video 3)'
},
{
id: 'Xrx2TiiF90Q',
title: 'Receive Lightning Network payment - Zap Lightning Network Wallet Tutorial (Video 4)'
},
{
id: 'YfxukBHnwUM',
title: 'Network Map - Zap Lightning Network Wallet Tutorial (Video 5)'
},
{
id: 'NORklrrYzOg',
title: 'Using an explorer to add Zap contacts - Zap Lightning Network Wallet Tutorial (Video 6)'
}
],
searchQuery: ''
}
}
render() {
const { videos, searchQuery } = this.state
const filteredVideos = videos.filter(video => video.title.includes(searchQuery))
return (
<div className={styles.helpContainer}>
<header className={styles.header}>
<h1>Video tutorials</h1>
</header>
<div className={styles.search}>
<label className={`${styles.label} ${styles.input}`} htmlFor='helpSearch'>
<MdSearch />
</label>
<input
value={searchQuery}
onChange={event => this.setState({ searchQuery: event.target.value })}
className={`${styles.text} ${styles.input}`}
placeholder='Search the video library...'
type='text'
id='helpSearch'
/>
</div>
<ul className={styles.videos}>
{
filteredVideos.map((video, index) => (
<li key={index}>
<iframe
src={`https://www.youtube.com/embed/${video.id}`}
frameBorder='0'
title={video.id}
/>
<section className={styles.info} onClick={() => shell.openExternal(`https://www.youtube.com/watch?v=${video.id}`)}>
<h2>{video.title}</h2>
</section>
</li>
))
}
</ul>
</div>
)
}
}
export default Help

90
app/routes/help/components/Help.scss

@ -1,90 +0,0 @@
@import '../../../variables.scss';
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
background: $lightgrey;
padding: 20px 40px;
h1 {
text-transform: uppercase;
font-size: 26px;
margin-right: 5px;
}
}
.search {
height: 55px;
padding: 2px 25px;
border-top: 1px solid $darkgrey;
border-bottom: 1px solid $darkgrey;
background: $white;
.input {
display: inline-block;
vertical-align: top;
height: 100%;
}
.label {
width: 5%;
line-height: 50px;
font-size: 20px;
text-align: center;
cursor: pointer;
}
.text {
width: 95%;
outline: 0;
padding: 0;
border: 0;
border-radius: 0;
height: 50px;
font-size: 16px;
}
}
.videos {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
padding: 20px 40px;
li {
position: relative;
width: 50%;
text-align: center;
margin: 20px 0;
width: 400px;
height: 400px;
transition: all 0.25s;
&:hover {
opacity: 0.5;
.info {
padding: 50px 15px;
}
}
iframe {
width: 100%;
height: 100%;
}
.info {
position: absolute;
bottom: 0;
width: calc(100% - 30px);
padding: 15px;
background: $darkgrey;
cursor: pointer;
transition: all 0.25s;
text-align: left;
line-height: 1.5;
}
}
}

10
app/routes/help/containers/HelpContainer.js

@ -1,10 +0,0 @@
import { withRouter } from 'react-router'
import { connect } from 'react-redux'
import Help from '../components/Help'
const mapDispatchToProps = {}
const mapStateToProps = () => ({})
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Help))

3
app/routes/help/index.js

@ -1,3 +0,0 @@
import HelpContainer from './containers/HelpContainer'
export default HelpContainer

168
app/routes/network/components/Network.js

@ -1,168 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import CanvasNetworkGraph from 'components/Network/CanvasNetworkGraph'
import PeersList from 'components/Network/PeersList'
import ChannelsList from 'components/Network/ChannelsList'
import TransactionForm from 'components/Network/TransactionForm'
import styles from './Network.scss'
class Network extends Component {
componentWillMount() {
const { fetchDescribeNetwork, fetchPeers, fetchChannels } = this.props
fetchPeers()
fetchChannels()
fetchDescribeNetwork()
}
componentDidUpdate(prevProps) {
const {
payReqIsLn, network: { pay_req }, fetchInvoiceAndQueryRoutes, clearQueryRoutes
} = this.props
// If LN go retrieve invoice details
if ((prevProps.network.pay_req !== pay_req) && payReqIsLn) {
fetchInvoiceAndQueryRoutes(pay_req)
}
if (prevProps.payReqIsLn && !payReqIsLn) {
clearQueryRoutes()
}
}
componentWillUnmount() {
const {
clearQueryRoutes, resetPayReq, clearSelectedChannels, clearSelectedPeers
} = this.props
clearQueryRoutes()
resetPayReq()
clearSelectedChannels()
clearSelectedPeers()
}
render() {
const {
setCurrentTab,
updateSelectedPeers,
setCurrentRoute,
network,
selectedPeerPubkeys,
currentRouteChanIds,
peers: { peers },
activeChannels,
selectedChannelIds,
updateSelectedChannels,
updatePayReq,
identity_pubkey
} = this.props
const renderContent = () => {
switch (network.currentTab) {
case 1:
return <PeersList peers={peers} updateSelectedPeers={updateSelectedPeers} selectedPeerPubkeys={selectedPeerPubkeys} />
case 2:
return <ChannelsList channels={activeChannels} updateSelectedChannels={updateSelectedChannels} selectedChannelIds={selectedChannelIds} />
case 3:
return (
<TransactionForm
updatePayReq={updatePayReq}
pay_req={network.pay_req}
loadingRoutes={network.fetchingInvoiceAndQueryingRoutes}
payReqRoutes={network.payReqRoutes}
setCurrentRoute={setCurrentRoute}
currentRoute={network.currentRoute}
/>
)
default:
return <span />
}
}
return (
<div className={styles.container}>
{
!network.networkLoading &&
<section className={styles.stats}>
<span>{network.nodes.length} nodes</span>
<span>|</span>
<span>{network.edges.length} channels</span>
</section>
}
<CanvasNetworkGraph
className={styles.network}
network={network}
identity_pubkey={identity_pubkey}
selectedPeerPubkeys={selectedPeerPubkeys}
selectedChannelIds={selectedChannelIds}
currentRouteChanIds={currentRouteChanIds}
/>
<section className={styles.toolbox}>
<ul className={styles.tabs}>
<li
className={`${styles.tab} ${styles.peersTab} ${network.currentTab === 1 && styles.active}`}
onClick={() => setCurrentTab(1)}
>
Peers
</li>
<li
className={`${styles.tab} ${styles.channelsTab} ${network.currentTab === 2 && styles.active}`}
onClick={() => setCurrentTab(2)}
>
Channels
</li>
<li
className={`${styles.tab} ${styles.transactionsTab} ${network.currentTab === 3 && styles.active}`}
onClick={() => setCurrentTab(3)}
>
Transactions
</li>
</ul>
<div className={styles.content}>
{renderContent()}
</div>
</section>
</div>
)
}
}
Network.propTypes = {
fetchDescribeNetwork: PropTypes.func.isRequired,
fetchPeers: PropTypes.func.isRequired,
setCurrentTab: PropTypes.func.isRequired,
fetchChannels: PropTypes.func.isRequired,
fetchInvoiceAndQueryRoutes: PropTypes.func.isRequired,
clearQueryRoutes: PropTypes.func.isRequired,
resetPayReq: PropTypes.func.isRequired,
clearSelectedChannels: PropTypes.func.isRequired,
clearSelectedPeers: PropTypes.func.isRequired,
updateSelectedPeers: PropTypes.func.isRequired,
setCurrentRoute: PropTypes.func.isRequired,
updateSelectedChannels: PropTypes.func.isRequired,
updatePayReq: PropTypes.func.isRequired,
network: PropTypes.object.isRequired,
peers: PropTypes.object.isRequired,
selectedPeerPubkeys: PropTypes.array.isRequired,
currentRouteChanIds: PropTypes.array.isRequired,
activeChannels: PropTypes.array.isRequired,
selectedChannelIds: PropTypes.array.isRequired,
identity_pubkey: PropTypes.string.isRequired,
payReqIsLn: PropTypes.bool.isRequired
}
export default Network

99
app/routes/network/components/Network.scss

@ -1,99 +0,0 @@
@import '../../../variables.scss';
@keyframes dash {
to {
stroke-dashoffset: 1000;
}
}
@keyframes fadein {
0% { background: $white; }
50% { background: lighten($secondary, 50%); }
100% { background: $secondary; animation-fill-mode:forwards; }
}
.container {
width: 100%;
height: 100vh;
animation: fadein 0.5s;
animation-timing-function:linear;
animation-fill-mode:forwards;
animation-iteration-count: 1;
line.active {
opacity: 1;
stroke: green;
stroke-width: 5;
stroke-dasharray: 100;
animation: dash 2.5s infinite linear;
}
circle {
cursor: pointer;
}
.stats {
position: absolute;
top: 0;
right: 30%;
padding: 20px;
span {
color: $main;
margin: 0 2.5px;
line-height: 25px;
vertical-align: middle;
&:nth-child(2) {
font-size: 25px;
}
}
}
}
.network, .toolbox {
display: inline-block;
vertical-align: top;
height: 100vh;
}
.network {
width: 70%;
}
.toolbox {
width: 30%;
height: 100%;
background: #353535;
overflow-y: scroll;
}
.tabs {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-top: 40px;
.tab {
color: $white;
text-align: center;
cursor: pointer;
width: 100%;
padding: 10px 0;
border-bottom: 1px solid #464646;
transition: all 0.5s;
&.peersTab:hover, &.peersTab.active {
border-bottom: 1px solid #588CF0;
}
&.channelsTab:hover, &.channelsTab.active {
border-bottom: 1px solid #88D4A2;
}
&.transactionsTab:hover, &.transactionsTab.active {
border-bottom: 1px solid #FFDC53;
}
}
}

62
app/routes/network/containers/NetworkContainer.js

@ -1,62 +0,0 @@
import { withRouter } from 'react-router'
import { connect } from 'react-redux'
import {
fetchDescribeNetwork,
setCurrentTab,
updateSelectedPeers,
clearSelectedPeers,
updateSelectedChannels,
clearSelectedChannels,
setCurrentRoute,
updatePayReq,
resetPayReq,
fetchInvoiceAndQueryRoutes,
clearQueryRoutes,
networkSelectors
} from '../../../reducers/network'
import { fetchPeers } from '../../../reducers/peers'
import { fetchChannels, channelsSelectors } from '../../../reducers/channels'
import Network from '../components/Network'
const mapDispatchToProps = {
fetchDescribeNetwork,
setCurrentTab,
updateSelectedPeers,
clearSelectedPeers,
updatePayReq,
fetchInvoiceAndQueryRoutes,
setCurrentRoute,
clearQueryRoutes,
resetPayReq,
fetchPeers,
fetchChannels,
updateSelectedChannels,
clearSelectedChannels
}
const mapStateToProps = state => ({
network: state.network,
peers: state.peers,
identity_pubkey: state.info.data.identity_pubkey,
selectedPeerPubkeys: networkSelectors.selectedPeerPubkeys(state),
selectedChannelIds: networkSelectors.selectedChannelIds(state),
payReqIsLn: networkSelectors.payReqIsLn(state),
currentRouteChanIds: networkSelectors.currentRouteChanIds(state),
activeChannels: channelsSelectors.activeChannels(state)
})
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Network))

3
app/routes/network/index.js

@ -1,3 +0,0 @@
import NetworkContainer from './containers/NetworkContainer'
export default NetworkContainer
Loading…
Cancel
Save