2017-10-04 04:37:06 +00:00
|
|
|
import {
|
|
|
|
TChangeGasPrice,
|
|
|
|
TChangeLanguage,
|
2017-11-18 20:33:53 +00:00
|
|
|
TChangeNodeIntent,
|
|
|
|
TAddCustomNode,
|
2017-12-01 16:09:51 +00:00
|
|
|
TRemoveCustomNode,
|
|
|
|
TAddCustomNetwork
|
2017-10-04 04:37:06 +00:00
|
|
|
} from 'actions/config';
|
2017-09-25 02:06:28 +00:00
|
|
|
import logo from 'assets/images/logo-myetherwallet.svg';
|
2017-10-02 22:36:59 +00:00
|
|
|
import { Dropdown, ColorDropdown } from 'components/ui';
|
2017-05-23 23:06:01 +00:00
|
|
|
import React, { Component } from 'react';
|
2017-11-18 20:33:53 +00:00
|
|
|
import classnames from 'classnames';
|
2017-09-29 02:09:01 +00:00
|
|
|
import { Link } from 'react-router-dom';
|
2017-08-25 07:37:36 +00:00
|
|
|
import {
|
2017-09-25 02:06:28 +00:00
|
|
|
ANNOUNCEMENT_MESSAGE,
|
|
|
|
ANNOUNCEMENT_TYPE,
|
2017-08-25 07:37:36 +00:00
|
|
|
languages,
|
2017-09-25 02:06:28 +00:00
|
|
|
NODES,
|
2017-11-18 20:33:53 +00:00
|
|
|
VERSION,
|
|
|
|
NodeConfig,
|
2017-12-01 16:09:51 +00:00
|
|
|
CustomNodeConfig,
|
|
|
|
CustomNetworkConfig
|
|
|
|
} from 'config/data';
|
2017-09-25 02:06:28 +00:00
|
|
|
import GasPriceDropdown from './components/GasPriceDropdown';
|
|
|
|
import Navigation from './components/Navigation';
|
2017-11-18 20:33:53 +00:00
|
|
|
import CustomNodeModal from './components/CustomNodeModal';
|
2017-09-26 23:03:38 +00:00
|
|
|
import { getKeyByValue } from 'utils/helpers';
|
2017-11-18 20:33:53 +00:00
|
|
|
import { makeCustomNodeId } from 'utils/node';
|
2017-12-01 16:09:51 +00:00
|
|
|
import { getNetworkConfigFromId } from 'utils/network';
|
2017-07-15 04:16:36 +00:00
|
|
|
import './index.scss';
|
|
|
|
|
2017-09-25 02:06:28 +00:00
|
|
|
interface Props {
|
|
|
|
languageSelection: string;
|
2017-11-18 20:33:53 +00:00
|
|
|
node: NodeConfig;
|
2017-09-25 02:06:28 +00:00
|
|
|
nodeSelection: string;
|
2017-11-18 20:33:53 +00:00
|
|
|
isChangingNode: boolean;
|
2017-09-25 02:06:28 +00:00
|
|
|
gasPriceGwei: number;
|
2017-11-18 20:33:53 +00:00
|
|
|
customNodes: CustomNodeConfig[];
|
2017-12-01 16:09:51 +00:00
|
|
|
customNetworks: CustomNetworkConfig[];
|
2017-06-18 19:56:12 +00:00
|
|
|
|
2017-09-25 02:06:28 +00:00
|
|
|
changeLanguage: TChangeLanguage;
|
2017-10-04 04:37:06 +00:00
|
|
|
changeNodeIntent: TChangeNodeIntent;
|
2017-09-25 02:06:28 +00:00
|
|
|
changeGasPrice: TChangeGasPrice;
|
2017-11-18 20:33:53 +00:00
|
|
|
addCustomNode: TAddCustomNode;
|
|
|
|
removeCustomNode: TRemoveCustomNode;
|
2017-12-01 16:09:51 +00:00
|
|
|
addCustomNetwork: TAddCustomNetwork;
|
2017-09-25 02:06:28 +00:00
|
|
|
}
|
2017-04-12 05:04:27 +00:00
|
|
|
|
2017-11-18 20:33:53 +00:00
|
|
|
interface State {
|
|
|
|
isAddingCustomNode: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default class Header extends Component<Props, State> {
|
|
|
|
public state = {
|
|
|
|
isAddingCustomNode: false
|
|
|
|
};
|
|
|
|
|
2017-09-25 02:06:28 +00:00
|
|
|
public render() {
|
2017-11-18 20:33:53 +00:00
|
|
|
const {
|
|
|
|
languageSelection,
|
|
|
|
changeNodeIntent,
|
|
|
|
node,
|
|
|
|
nodeSelection,
|
|
|
|
isChangingNode,
|
2017-12-01 16:09:51 +00:00
|
|
|
customNodes,
|
|
|
|
customNetworks
|
2017-11-18 20:33:53 +00:00
|
|
|
} = this.props;
|
|
|
|
const { isAddingCustomNode } = this.state;
|
2017-09-26 23:03:38 +00:00
|
|
|
const selectedLanguage = languageSelection;
|
2017-12-01 16:09:51 +00:00
|
|
|
const selectedNetwork = getNetworkConfigFromId(
|
|
|
|
node.network,
|
|
|
|
customNetworks
|
|
|
|
);
|
2017-09-25 02:06:28 +00:00
|
|
|
const LanguageDropDown = Dropdown as new () => Dropdown<
|
|
|
|
typeof selectedLanguage
|
|
|
|
>;
|
2017-11-18 20:33:53 +00:00
|
|
|
|
|
|
|
const nodeOptions = Object.keys(NODES)
|
|
|
|
.map(key => {
|
2017-12-01 16:09:51 +00:00
|
|
|
const n = NODES[key];
|
|
|
|
const network = getNetworkConfigFromId(n.network, customNetworks);
|
2017-11-18 20:33:53 +00:00
|
|
|
return {
|
|
|
|
value: key,
|
|
|
|
name: (
|
|
|
|
<span>
|
2017-12-01 16:09:51 +00:00
|
|
|
{network && network.name} <small>({n.service})</small>
|
2017-11-18 20:33:53 +00:00
|
|
|
</span>
|
|
|
|
),
|
2017-12-01 16:09:51 +00:00
|
|
|
color: network && network.color,
|
|
|
|
hidden: n.hidden
|
2017-11-18 20:33:53 +00:00
|
|
|
};
|
|
|
|
})
|
|
|
|
.concat(
|
2017-12-01 16:09:51 +00:00
|
|
|
customNodes.map(cn => {
|
|
|
|
const network = getNetworkConfigFromId(cn.network, customNetworks);
|
2017-11-18 20:33:53 +00:00
|
|
|
return {
|
2017-12-01 16:09:51 +00:00
|
|
|
value: makeCustomNodeId(cn),
|
2017-11-18 20:33:53 +00:00
|
|
|
name: (
|
|
|
|
<span>
|
2017-12-01 16:09:51 +00:00
|
|
|
{network && network.name} - {cn.name} <small>(custom)</small>
|
2017-11-18 20:33:53 +00:00
|
|
|
</span>
|
|
|
|
),
|
2017-12-01 16:09:51 +00:00
|
|
|
color: network && network.color,
|
2017-11-18 20:33:53 +00:00
|
|
|
hidden: false,
|
2017-12-01 16:09:51 +00:00
|
|
|
onRemove: () => this.props.removeCustomNode(cn)
|
2017-11-18 20:33:53 +00:00
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
2017-10-02 22:36:59 +00:00
|
|
|
|
2017-07-02 05:49:06 +00:00
|
|
|
return (
|
2017-07-15 04:16:36 +00:00
|
|
|
<div className="Header">
|
2017-09-25 02:06:28 +00:00
|
|
|
{ANNOUNCEMENT_MESSAGE && (
|
2017-08-25 07:37:36 +00:00
|
|
|
<div
|
|
|
|
className={`Header-announcement is-${ANNOUNCEMENT_TYPE}`}
|
|
|
|
dangerouslySetInnerHTML={{
|
|
|
|
__html: ANNOUNCEMENT_MESSAGE
|
|
|
|
}}
|
2017-09-25 02:06:28 +00:00
|
|
|
/>
|
|
|
|
)}
|
2017-08-25 07:37:36 +00:00
|
|
|
|
2017-07-15 04:16:36 +00:00
|
|
|
<section className="Header-branding">
|
|
|
|
<section className="Header-branding-inner container">
|
|
|
|
<Link
|
2017-11-18 20:33:53 +00:00
|
|
|
to="/"
|
2017-07-15 04:16:36 +00:00
|
|
|
className="Header-branding-title"
|
|
|
|
aria-label="Go to homepage"
|
|
|
|
>
|
|
|
|
{/* TODO - don't hardcode image path*/}
|
|
|
|
<img
|
|
|
|
className="Header-branding-title-logo"
|
|
|
|
src={logo}
|
|
|
|
height="64px"
|
|
|
|
width="245px"
|
|
|
|
alt="MyEtherWallet"
|
|
|
|
/>
|
2017-07-02 05:49:06 +00:00
|
|
|
</Link>
|
2017-10-02 22:36:59 +00:00
|
|
|
<div className="Header-branding-right">
|
|
|
|
<span className="Header-branding-right-version">v{VERSION}</span>
|
2017-07-15 04:16:36 +00:00
|
|
|
|
2017-10-02 22:36:59 +00:00
|
|
|
<div className="Header-branding-right-dropdown">
|
|
|
|
<GasPriceDropdown
|
|
|
|
value={this.props.gasPriceGwei}
|
|
|
|
onChange={this.props.changeGasPrice}
|
|
|
|
/>
|
|
|
|
</div>
|
2017-07-20 17:06:10 +00:00
|
|
|
|
2017-10-02 22:36:59 +00:00
|
|
|
<div className="Header-branding-right-dropdown">
|
|
|
|
<LanguageDropDown
|
2017-11-12 19:45:52 +00:00
|
|
|
ariaLabel={`change language. current language ${
|
|
|
|
languages[selectedLanguage]
|
|
|
|
}`}
|
2017-10-02 22:36:59 +00:00
|
|
|
options={Object.values(languages)}
|
|
|
|
value={languages[selectedLanguage]}
|
|
|
|
extra={
|
|
|
|
<li key="disclaimer">
|
|
|
|
<a data-toggle="modal" data-target="#disclaimerModal">
|
|
|
|
Disclaimer
|
|
|
|
</a>
|
|
|
|
</li>
|
|
|
|
}
|
|
|
|
onChange={this.changeLanguage}
|
|
|
|
size="smr"
|
|
|
|
color="white"
|
|
|
|
/>
|
|
|
|
</div>
|
2017-07-15 04:16:36 +00:00
|
|
|
|
2017-11-18 20:33:53 +00:00
|
|
|
<div
|
|
|
|
className={classnames({
|
|
|
|
'Header-branding-right-dropdown': true,
|
|
|
|
'is-flashing': isChangingNode
|
|
|
|
})}
|
|
|
|
>
|
2017-10-02 22:36:59 +00:00
|
|
|
<ColorDropdown
|
2017-11-18 20:33:53 +00:00
|
|
|
ariaLabel={`
|
2017-12-01 16:09:51 +00:00
|
|
|
change node. current node is on the ${node.network} network
|
|
|
|
provided by ${node.service}
|
2017-11-18 20:33:53 +00:00
|
|
|
`}
|
2017-10-02 22:36:59 +00:00
|
|
|
options={nodeOptions}
|
|
|
|
value={nodeSelection}
|
|
|
|
extra={
|
|
|
|
<li>
|
2017-11-18 20:33:53 +00:00
|
|
|
<a onClick={this.openCustomNodeModal}>Add Custom Node</a>
|
2017-10-02 22:36:59 +00:00
|
|
|
</li>
|
|
|
|
}
|
2017-11-10 03:30:20 +00:00
|
|
|
disabled={nodeSelection === 'web3'}
|
2017-10-04 04:37:06 +00:00
|
|
|
onChange={changeNodeIntent}
|
2017-10-02 22:36:59 +00:00
|
|
|
size="smr"
|
|
|
|
color="white"
|
2017-11-18 20:33:53 +00:00
|
|
|
menuAlign="right"
|
2017-10-02 22:36:59 +00:00
|
|
|
/>
|
|
|
|
</div>
|
2017-07-02 05:49:06 +00:00
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</section>
|
2017-04-18 23:36:29 +00:00
|
|
|
|
2017-12-01 16:09:51 +00:00
|
|
|
<Navigation color={selectedNetwork && selectedNetwork.color} />
|
2017-11-18 20:33:53 +00:00
|
|
|
|
|
|
|
{isAddingCustomNode && (
|
|
|
|
<CustomNodeModal
|
2017-12-01 16:09:51 +00:00
|
|
|
customNodes={customNodes}
|
|
|
|
customNetworks={customNetworks}
|
2017-11-18 20:33:53 +00:00
|
|
|
handleAddCustomNode={this.addCustomNode}
|
2017-12-01 16:09:51 +00:00
|
|
|
handleAddCustomNetwork={this.props.addCustomNetwork}
|
2017-11-18 20:33:53 +00:00
|
|
|
handleClose={this.closeCustomNodeModal}
|
|
|
|
/>
|
|
|
|
)}
|
2017-07-02 05:49:06 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2017-07-04 01:25:01 +00:00
|
|
|
|
2017-09-26 23:03:38 +00:00
|
|
|
public changeLanguage = (value: string) => {
|
|
|
|
const key = getKeyByValue(languages, value);
|
|
|
|
if (key) {
|
|
|
|
this.props.changeLanguage(key);
|
|
|
|
}
|
2017-07-04 03:21:19 +00:00
|
|
|
};
|
2017-11-18 20:33:53 +00:00
|
|
|
|
|
|
|
private openCustomNodeModal = () => {
|
|
|
|
this.setState({ isAddingCustomNode: true });
|
|
|
|
};
|
|
|
|
|
|
|
|
private closeCustomNodeModal = () => {
|
|
|
|
this.setState({ isAddingCustomNode: false });
|
|
|
|
};
|
|
|
|
|
|
|
|
private addCustomNode = (node: CustomNodeConfig) => {
|
|
|
|
this.setState({ isAddingCustomNode: false });
|
|
|
|
this.props.addCustomNode(node);
|
|
|
|
};
|
2017-04-12 05:04:27 +00:00
|
|
|
}
|