Add network list dropdown in UI (#330)
This commit is contained in:
parent
62f9a080c9
commit
d3576f5a79
@ -24,3 +24,4 @@
|
||||
@import "components/mobile-menu";
|
||||
@import "components/mobile-menu-button";
|
||||
@import "components/social-icons";
|
||||
@import "components/NetworkSelect";
|
||||
|
164
ui/src/assets/stylesheets/components/_NetworkSelect.scss
Normal file
164
ui/src/assets/stylesheets/components/_NetworkSelect.scss
Normal file
@ -0,0 +1,164 @@
|
||||
.NetworkSelect {
|
||||
display: flex;
|
||||
@media (min-width: $tablet-width) {
|
||||
position: relative;
|
||||
margin-left: 10px;
|
||||
&:hover {
|
||||
.NetworkSelect_List {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sw-Header_Content .NetworkSelect {
|
||||
display: none;
|
||||
@media (min-width: $tablet-width) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.NetworkSelect_Top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 1;
|
||||
transition: .15s ease-in;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
@media screen and (max-width: $mobile-width) {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
@media (min-width: $tablet-width) {
|
||||
.nl-IconNetwork_Arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nl-NavigationLinks_Link.opacityFull {
|
||||
opacity: 1;
|
||||
flex-direction: column;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.nl-IconNetwork_Arrow {
|
||||
margin-left: 10px;
|
||||
transition: .15s ease-in;
|
||||
path {
|
||||
fill: #fff;
|
||||
opacity: .52;
|
||||
}
|
||||
}
|
||||
|
||||
.NetworkSelect_List {
|
||||
z-index: 999;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
@media (min-width: $tablet-width) {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
width: 160px;
|
||||
border-radius: 4px 0 4px 4px;
|
||||
box-shadow: 0 5px 10px rgba(#000, .05);
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
li.currentNetwork {
|
||||
@media (max-width: $tablet-width) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
button {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
transition: .15s ease-in;
|
||||
height: 50px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
@media (min-width: $tablet-width) {
|
||||
padding: 8px 18px;
|
||||
height: auto;
|
||||
color: $text-color;
|
||||
justify-content: flex-start;
|
||||
&:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nl-NavigationLinks {
|
||||
display: flex;
|
||||
|
||||
.hd-MobileMenuLinks & {
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.nl-NavigationLinks_Link {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
margin-left: 0;
|
||||
opacity: 0.7;
|
||||
text-decoration: none;
|
||||
transition: opacity ease-in 0.15s, background-color ease-in 0.15s;
|
||||
|
||||
&:active,
|
||||
&:hover,
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.active {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hd-MobileMenuLinks & {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
height: 50px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: $tablet-width) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.nl-NavigationLinks_Text {
|
||||
margin-left: 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nl-IconNetwork_Path {
|
||||
fill: #60db97;
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
max-width: 700px;
|
||||
@media screen and (max-width: $mobile-width) {
|
||||
display: none;
|
||||
}
|
||||
@ -10,4 +9,4 @@
|
||||
justify-content: flex-end;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,4 +23,4 @@
|
||||
path {
|
||||
fill: $header-menu-icon-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
.mobile-menu {
|
||||
@media screen and (max-width: $mobile-width) {
|
||||
background-color: $mobile-menu-background-color;
|
||||
height: 172px;
|
||||
height: 272px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,4 +30,4 @@
|
||||
min-height: 100%;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import { toDecimals } from '../stores/utils/decimals'
|
||||
@observer
|
||||
export class Bridge extends React.Component {
|
||||
state = {
|
||||
reverse: false,
|
||||
amount: '',
|
||||
modalData: {},
|
||||
confirmationData: {},
|
||||
@ -38,25 +37,6 @@ export class Bridge extends React.Component {
|
||||
web3Store.getWeb3Promise.then(() => {
|
||||
if (!web3Store.metamaskNet.id || !web3Store.foreignNet.id) {
|
||||
this.forceUpdate()
|
||||
} else {
|
||||
const reverse = web3Store.metamaskNet.id.toString() === web3Store.foreignNet.id.toString()
|
||||
if (reverse) {
|
||||
this.setState({
|
||||
reverse
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { web3Store } = this.props.RootStore
|
||||
web3Store.getWeb3Promise.then(() => {
|
||||
const reverse = web3Store.metamaskNet.id.toString() === web3Store.foreignNet.id.toString()
|
||||
if (reverse !== this.state.reverse) {
|
||||
this.setState({
|
||||
reverse
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -202,7 +182,7 @@ export class Bridge extends React.Component {
|
||||
return
|
||||
}
|
||||
|
||||
const { reverse } = this.state
|
||||
const { reverse } = web3Store
|
||||
const homeDisplayName = homeStore.networkName
|
||||
const foreignDisplayName = foreignStore.networkName
|
||||
|
||||
@ -230,8 +210,8 @@ export class Bridge extends React.Component {
|
||||
}
|
||||
|
||||
onTransferConfirmation = async () => {
|
||||
const { alertStore } = this.props.RootStore
|
||||
const { reverse } = this.state
|
||||
const { alertStore, web3Store } = this.props.RootStore
|
||||
const { reverse } = web3Store
|
||||
|
||||
this.setState({ showConfirmation: false, confirmationData: {} })
|
||||
const amount = this.state.amount.trim()
|
||||
@ -333,7 +313,8 @@ export class Bridge extends React.Component {
|
||||
|
||||
render() {
|
||||
const { web3Store, foreignStore, homeStore } = this.props.RootStore
|
||||
const { reverse, showModal, modalData, showConfirmation, confirmationData } = this.state
|
||||
const { showModal, modalData, showConfirmation, confirmationData } = this.state
|
||||
const { reverse } = web3Store
|
||||
const formCurrency = reverse ? foreignStore.symbol : homeStore.symbol
|
||||
|
||||
if (showModal && Object.keys(modalData).length !== 0) {
|
||||
|
@ -30,7 +30,7 @@ export class DailyQuotaModal extends React.Component {
|
||||
const { web3Store, homeStore, foreignStore } = this.props.RootStore
|
||||
const { left, top } = this.state
|
||||
|
||||
const isHome = web3Store.metamaskNet.id.toString() === web3Store.homeNet.id.toString()
|
||||
const isHome = web3Store.isSelectedNetwork(web3Store.homeNet.id)
|
||||
const value = isHome ? homeStore.maxCurrentDeposit : foreignStore.maxCurrentDeposit
|
||||
const limit = isHome ? homeStore.maxPerTx : foreignStore.maxPerTx
|
||||
const from = isHome ? homeStore.symbol : foreignStore.symbol
|
||||
|
@ -17,7 +17,7 @@ export class Header extends React.Component {
|
||||
RootStore: { alertStore, web3Store }
|
||||
} = this.props
|
||||
const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env
|
||||
const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN)
|
||||
const withoutEvents = web3Store.isSelectedNetwork(web3Store.homeNet.id) ? yn(HOME) : yn(FOREIGN)
|
||||
|
||||
return (
|
||||
<header className="header">
|
||||
|
@ -1,10 +1,12 @@
|
||||
import React from 'react'
|
||||
import { MenuItems } from './MenuItems'
|
||||
import { Wallet } from './Wallet'
|
||||
import NetworkSelect from './NetworkSelect'
|
||||
|
||||
export const HeaderMenu = ({ withoutEvents }) => (
|
||||
<div className="header-menu">
|
||||
<MenuItems withoutEvents={withoutEvents} />
|
||||
<Wallet />
|
||||
<NetworkSelect />
|
||||
</div>
|
||||
)
|
||||
|
@ -1,10 +1,12 @@
|
||||
import React from 'react'
|
||||
import { MenuItems } from './MenuItems'
|
||||
import NetworkSelect from './NetworkSelect'
|
||||
|
||||
export const MobileMenu = ({ onMenuToggle, withoutEvents }) => (
|
||||
<div className="mobile-menu">
|
||||
<div className="mobile-menu-links">
|
||||
<MenuItems withoutEvents={withoutEvents} onMenuToggle={onMenuToggle} />
|
||||
<NetworkSelect />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
62
ui/src/components/NetworkSelect.js
Normal file
62
ui/src/components/NetworkSelect.js
Normal file
@ -0,0 +1,62 @@
|
||||
import React, { Component } from 'react'
|
||||
import { inject, observer } from 'mobx-react'
|
||||
|
||||
@inject('RootStore')
|
||||
@observer
|
||||
export default class NetworkSelect extends Component {
|
||||
changeNetworkRPC(e) {
|
||||
const { web3Store } = this.props.RootStore
|
||||
const newNetworkName = e.target.innerHTML
|
||||
web3Store.setSelectedNetwork(newNetworkName)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { web3Store } = this.props.RootStore
|
||||
let currentNetworkFullName = ''
|
||||
|
||||
const networks = web3Store.homeNet.id && web3Store.foreignNet.id ? [web3Store.homeNet, web3Store.foreignNet] : []
|
||||
let selectedNetworkIndex = -1
|
||||
|
||||
networks.forEach((network, i) => {
|
||||
if (web3Store.isSelectedNetwork(network.id)) {
|
||||
currentNetworkFullName = network.name
|
||||
selectedNetworkIndex = i
|
||||
}
|
||||
})
|
||||
|
||||
if (selectedNetworkIndex === -1) {
|
||||
selectedNetworkIndex = 0
|
||||
currentNetworkFullName = networks[0] ? networks[0].name : ''
|
||||
}
|
||||
|
||||
const listItems = networks.map((network, index) => {
|
||||
let className = ''
|
||||
if (index === selectedNetworkIndex) {
|
||||
className = 'currentNetwork'
|
||||
}
|
||||
return (
|
||||
<li key={network.name} className={className}>
|
||||
<button onClick={e => this.changeNetworkRPC(e)}>{network.name}</button>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={`NetworkSelect nl-NavigationLinks_Link opacityFull`}>
|
||||
<div className={`NetworkSelect_Top`}>
|
||||
<svg className={`nl-IconNetwork`} xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path
|
||||
className={`nl-IconNetwork_Path`}
|
||||
d="M9 18a9 9 0 0 1-9-9 9 9 0 0 1 9-9 9 9 0 0 1 9 9 9 9 0 0 1-9 9zm6.923-8h-1.974c-.116 1.85-.525 3.539-1.167 4.876A6.993 6.993 0 0 0 15.923 10zM9 16c1.51 0 2.747-2.612 2.957-6H6.043c.21 3.388 1.447 6 2.957 6zm-3.782-1.124C4.576 13.539 4.167 11.85 4.051 10H2.077a6.993 6.993 0 0 0 3.141 4.876zM2.077 8h1.974c.116-1.85.525-3.538 1.167-4.876A6.993 6.993 0 0 0 2.077 8zM9 2C7.49 2 6.253 4.612 6.043 8h5.914C11.747 4.612 10.51 2 9 2zm3.782 1.124C13.424 4.462 13.833 6.15 13.949 8h1.974a6.993 6.993 0 0 0-3.141-4.876z"
|
||||
/>
|
||||
</svg>
|
||||
<span className={`nl-NavigationLinks_Text`}>{currentNetworkFullName}</span>
|
||||
<svg className={`nl-IconNetwork_Arrow`} xmlns="http://www.w3.org/2000/svg" width="8" height="4">
|
||||
<path d="M0 0h8L4 4 0 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<ul className={`NetworkSelect_List`}>{listItems}</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -140,7 +140,7 @@ export class RelayEvents extends React.Component {
|
||||
const home = this.getHomeEvents(homeStore, foreignStore)
|
||||
const foreign = this.getForeignEvents(foreignStore, homeStore)
|
||||
const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env
|
||||
const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN)
|
||||
const withoutEvents = web3Store.isSelectedNetwork(web3Store.homeNet.id) ? yn(HOME) : yn(FOREIGN)
|
||||
|
||||
return withoutEvents ? (
|
||||
<Redirect to="/" />
|
||||
|
@ -17,7 +17,7 @@ export class StatisticsPage extends React.Component {
|
||||
const leftTitle = isNativeToErc ? 'Deposits' : 'Withdrawals'
|
||||
const rightTitle = isNativeToErc ? 'Withdrawals' : 'Deposits'
|
||||
const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env
|
||||
const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN)
|
||||
const withoutEvents = web3Store.isSelectedNetwork(web3Store.homeNet.id) ? yn(HOME) : yn(FOREIGN)
|
||||
|
||||
return withoutEvents ? (
|
||||
<Redirect to="/" />
|
||||
|
@ -9,7 +9,7 @@ import { inject, observer } from 'mobx-react'
|
||||
export class StatusPage extends React.Component {
|
||||
render() {
|
||||
const { homeStore, foreignStore, web3Store } = this.props.RootStore
|
||||
const isHome = web3Store.metamaskNet.id.toString() === web3Store.homeNet.id.toString()
|
||||
const isHome = web3Store.isSelectedNetwork(web3Store.homeNet.id)
|
||||
const requiredSignatures = isHome ? homeStore.requiredSignatures : foreignStore.requiredSignatures
|
||||
const authorities = isHome ? homeStore.validatorsCount : foreignStore.validatorsCount
|
||||
const symbol = isHome ? homeStore.symbol : foreignStore.symbol
|
||||
@ -17,7 +17,7 @@ export class StatusPage extends React.Component {
|
||||
const maxTotalBalance = isHome ? homeStore.maxCurrentDeposit : foreignStore.maxCurrentDeposit
|
||||
const validatorsList = isHome ? homeStore.validators : foreignStore.validators
|
||||
const { REACT_APP_UI_HOME_WITHOUT_EVENTS: HOME, REACT_APP_UI_FOREIGN_WITHOUT_EVENTS: FOREIGN } = process.env
|
||||
const withoutEvents = web3Store.metamaskNet.id === web3Store.homeNet.id.toString() ? yn(HOME) : yn(FOREIGN)
|
||||
const withoutEvents = web3Store.isSelectedNetwork(web3Store.homeNet.id) ? yn(HOME) : yn(FOREIGN)
|
||||
|
||||
return (
|
||||
<div className="status-page">
|
||||
|
@ -7,7 +7,7 @@ import { WalletIcon } from './menu-icons/WalletIcon'
|
||||
export class Wallet extends React.Component {
|
||||
render() {
|
||||
const { web3Store, homeStore, foreignStore, alertStore } = this.props.RootStore
|
||||
const isHome = web3Store.metamaskNet.id.toString() === web3Store.homeNet.id.toString()
|
||||
const isHome = web3Store.isSelectedNetwork(web3Store.homeNet.id)
|
||||
const address = web3Store.defaultAccount.address
|
||||
const explorerAddressUrl = isHome
|
||||
? homeStore.getExplorerAddressUrl(address)
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { action, observable } from 'mobx'
|
||||
import { action, computed, observable } from 'mobx'
|
||||
import getWeb3, { getBalance, getWeb3Instance, getNetwork } from './utils/web3'
|
||||
import { balanceLoaded } from './utils/testUtils'
|
||||
import { BRIDGE_MODES } from '../../../commons'
|
||||
import { toHex } from 'web3-utils'
|
||||
|
||||
class Web3Store {
|
||||
@observable
|
||||
@ -33,6 +34,9 @@ class Web3Store {
|
||||
@observable
|
||||
metamaskNet = { id: '', name: '' }
|
||||
|
||||
@observable
|
||||
selectedNet = { id: '', name: '' }
|
||||
|
||||
@observable
|
||||
walletInstalled = true
|
||||
|
||||
@ -145,6 +149,22 @@ class Web3Store {
|
||||
await this.setHomeWeb3Promise
|
||||
return this.metamaskNet.id === this.homeNet.id
|
||||
}
|
||||
|
||||
@action
|
||||
setSelectedNetwork(name) {
|
||||
const newNetwork = name === this.homeNet.name ? this.homeNet : this.foreignNet
|
||||
this.selectedNet = newNetwork
|
||||
}
|
||||
|
||||
isSelectedNetwork(id) {
|
||||
const compareNetwork = this.selectedNet.id ? this.selectedNet : this.metamaskNet
|
||||
return compareNetwork.id.toString() === id.toString()
|
||||
}
|
||||
|
||||
@computed
|
||||
get reverse() {
|
||||
return this.isSelectedNetwork(this.foreignNet.id)
|
||||
}
|
||||
}
|
||||
|
||||
export default Web3Store
|
||||
|
@ -60,11 +60,11 @@ const networks = {
|
||||
4: 'Rinkeby',
|
||||
30: 'RSK Mainnet',
|
||||
31: 'RSK Testnet',
|
||||
42: 'Kovan',
|
||||
42: 'Kovan Testnet',
|
||||
61: 'Ethereum Classic',
|
||||
77: 'Sokol',
|
||||
77: 'Sokol Testnet',
|
||||
99: 'POA Network',
|
||||
100: 'Dai Chain'
|
||||
100: 'xDai Chain'
|
||||
}
|
||||
|
||||
export const getNetworkName = id => networks[id] || 'Unknown'
|
||||
|
Loading…
Reference in New Issue
Block a user