MyCrypto/common/components/NetworkSelector/NetworkSelector.tsx

175 lines
5.0 KiB
TypeScript

import React from 'react';
import { connect } from 'react-redux';
import translate, { translateRaw } from 'translations';
import { NodeConfig } from 'types/node';
import { NetworkConfig } from 'types/network';
import { AppState } from 'features/reducers';
import {
TChangeNodeRequested,
changeNodeRequested,
TChangeNetworkRequested,
changeNetworkRequested,
getNodeConfig,
getNetworkConfig,
getAllNodes,
getAllNetworkConfigs
} from 'features/config';
import NetworkOption from './NetworkOption';
import './NetworkSelector.scss';
const CORE_NETWORKS = ['ETH', 'ETC', 'Ropsten', 'Kovan', 'Rinkeby'];
interface OwnProps {
openCustomNodeModal(): void;
onSelectNetwork?(network: NetworkConfig): void;
onSelectNode?(node: NodeConfig): void;
}
interface StateProps {
node: NodeConfig;
network: NetworkConfig;
allNodes: { [key: string]: NodeConfig };
allNetworks: { [key: string]: NetworkConfig };
}
interface DispatchProps {
changeNodeRequested: TChangeNodeRequested;
changeNetworkRequested: TChangeNetworkRequested;
}
interface State {
isShowingAltNetworks: boolean;
expandedNetwork: null | NetworkConfig;
}
type Props = OwnProps & StateProps & DispatchProps;
class NetworkSelector extends React.Component<Props> {
public state: State = {
isShowingAltNetworks: false,
expandedNetwork: null
};
public componentDidMount() {
const { node } = this.props;
const newState = { ...this.state };
// Expand alt networks by default if they're on one
if (!CORE_NETWORKS.includes(node.network)) {
newState.isShowingAltNetworks = true;
}
// Expand the network they're on if they selected a specific node
if (node.isCustom || !node.isAuto) {
newState.expandedNetwork = this.props.allNetworks[node.network];
}
this.setState(newState);
}
public render() {
const { allNodes, allNetworks, node } = this.props;
const { expandedNetwork, isShowingAltNetworks } = this.state;
const nodesByNetwork = {} as {
[network: string]: NodeConfig[];
};
Object.values(allNodes).forEach((n: NodeConfig) => {
if (!nodesByNetwork[n.network]) {
nodesByNetwork[n.network] = [];
}
nodesByNetwork[n.network].push(n);
}, {});
const options = {
core: [] as React.ReactElement<any>[],
alt: [] as React.ReactElement<any>[]
};
Object.keys(nodesByNetwork)
.sort((a, b) => {
// Sort by CORE_NETWORKS first, custom networks last
const idxA = CORE_NETWORKS.includes(a) ? CORE_NETWORKS.indexOf(a) : 999;
const idxB = CORE_NETWORKS.includes(b) ? CORE_NETWORKS.indexOf(b) : 999;
return idxA - idxB;
})
.forEach(netKey => {
const network = allNetworks[netKey];
const nodeType = CORE_NETWORKS.includes(netKey) || network.isCustom ? 'core' : 'alt';
options[nodeType].push(
<NetworkOption
key={netKey}
network={allNetworks[netKey]}
nodes={nodesByNetwork[netKey]}
nodeSelection={node.id}
isNetworkSelected={node.network === netKey}
isExpanded={expandedNetwork === allNetworks[netKey]}
selectNetwork={this.selectNetwork}
selectNode={this.selectNode}
toggleExpand={this.toggleNetworkExpand}
/>
);
});
return (
<div className="NetworkSelector">
{options.core}
<button className="NetworkSelector-alts" onClick={this.toggleShowAltNetworks}>
<i className="fa fa-flask" />
{translate(isShowingAltNetworks ? 'HIDE_THING' : 'SHOW_THING', {
$thing: translateRaw('NETWORKS_ALTERNATIVE')
})}
</button>
{isShowingAltNetworks && options.alt}
<button className="NetworkSelector-add" onClick={this.props.openCustomNodeModal}>
<i className="fa fa-plus" />
{translate('NODE_ADD')}
</button>
</div>
);
}
private selectNetwork = (net: NetworkConfig) => {
const { node } = this.props;
if (net.id === node.network && node.isAuto) {
return;
}
this.props.changeNetworkRequested(net.id);
if (this.props.onSelectNetwork) {
this.props.onSelectNetwork(net);
}
};
private selectNode = (node: NodeConfig) => {
if (node.id === this.props.node.id) {
return;
}
this.props.changeNodeRequested(node.id);
if (this.props.onSelectNode) {
this.props.onSelectNode(node);
}
};
private toggleNetworkExpand = (network: NetworkConfig) => {
this.setState({
expandedNetwork: network === this.state.expandedNetwork ? null : network
});
};
private toggleShowAltNetworks = () => {
this.setState({ isShowingAltNetworks: !this.state.isShowingAltNetworks });
};
}
export default connect(
(state: AppState): StateProps => ({
node: getNodeConfig(state),
network: getNetworkConfig(state),
allNodes: getAllNodes(state),
allNetworks: getAllNetworkConfigs(state)
}),
{
changeNodeRequested,
changeNetworkRequested
}
)(NetworkSelector);