ENS Search Styling (#1018)
* Restyled, recopied, and did some component refactoring for ENS. * Awkward copy fix. * Update snapshot. * Overflow table handling. * Re-enable on error.
This commit is contained in:
parent
df4b73721a
commit
7ac546acaf
|
@ -63,7 +63,7 @@ export default class Root extends Component<Props, State> {
|
|||
<Route path="/generate" component={GenerateWallet} />
|
||||
<Route path="/swap" component={Swap} />
|
||||
<Route path="/contracts" component={Contracts} />
|
||||
<Route path="/ens" component={ENS} />
|
||||
<Route path="/ens" component={ENS} exact={true} />
|
||||
<Route path="/sign-and-verify-message" component={SignAndVerifyMessage} />
|
||||
<Route path="/pushTx" component={BroadcastTx} />
|
||||
<RouteNotFound />
|
||||
|
|
|
@ -31,8 +31,8 @@ export interface AAttributes {
|
|||
|
||||
interface NewTabLinkProps extends AAttributes {
|
||||
href: string;
|
||||
content?: React.ReactElement<any> | string;
|
||||
children?: React.ReactElement<any> | string;
|
||||
content?: React.ReactElement<any> | string | string[];
|
||||
children?: React.ReactElement<any> | string | string[];
|
||||
}
|
||||
|
||||
export class NewTabLink extends React.Component<NewTabLinkProps> {
|
||||
|
|
|
@ -94,7 +94,7 @@ const GeneralInfoList = () => (
|
|||
</section>
|
||||
);
|
||||
|
||||
export const GeneralInfoPanel = () => (
|
||||
const GeneralInfoPanel = () => (
|
||||
<article className="block">
|
||||
<div className="cont-md">
|
||||
<h4> What is the process like? </h4>
|
||||
|
@ -113,3 +113,5 @@ export const GeneralInfoPanel = () => (
|
|||
</div>
|
||||
</article>
|
||||
);
|
||||
|
||||
export default GeneralInfoPanel;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
@import 'common/sass/variables';
|
||||
|
||||
.ENSInput {
|
||||
max-width: 520px;
|
||||
padding: $space-sm 0;
|
||||
margin: 0 auto;
|
||||
|
||||
&-name {
|
||||
margin-bottom: $space-md;
|
||||
}
|
||||
|
||||
&-button {
|
||||
.Spinner {
|
||||
margin-left: $space-md;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from 'reducers';
|
||||
import { resolveDomainRequested, TResolveDomainRequested } from 'actions/ens';
|
||||
import { isValidENSName } from 'libs/validators';
|
||||
import './NameInput.scss';
|
||||
|
||||
interface State {
|
||||
domainToCheck: string;
|
||||
isValidDomain: boolean;
|
||||
isFocused: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
domainRequests: AppState['ens']['domainRequests'];
|
||||
resolveDomainRequested: TResolveDomainRequested;
|
||||
}
|
||||
|
||||
class NameInput extends Component<Props, State> {
|
||||
public state = {
|
||||
isFocused: false,
|
||||
isValidDomain: false,
|
||||
domainToCheck: ''
|
||||
};
|
||||
|
||||
public render() {
|
||||
const { domainRequests } = this.props;
|
||||
const { isValidDomain, domainToCheck, isFocused } = this.state;
|
||||
const req = domainRequests[domainToCheck];
|
||||
const isLoading = req && !req.data && !req.error;
|
||||
|
||||
return (
|
||||
<form className="ENSInput" onSubmit={this.onSubmit}>
|
||||
<div className="ENSInput-name input-group">
|
||||
<input
|
||||
value={domainToCheck}
|
||||
className={classnames(
|
||||
'form-control',
|
||||
!domainToCheck ? '' : isValidDomain ? 'is-valid' : 'is-invalid'
|
||||
)}
|
||||
type="text"
|
||||
placeholder="mycrypto"
|
||||
onChange={this.onChange}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<span className="input-group-addon">.eth</span>
|
||||
</div>
|
||||
{domainToCheck &&
|
||||
!isValidDomain &&
|
||||
!isFocused && (
|
||||
<p className="help-block is-invalid">
|
||||
Must be at least 7 characters, no special characters
|
||||
</p>
|
||||
)}
|
||||
<button
|
||||
className="ENSInput-button btn btn-primary btn-block"
|
||||
disabled={!isValidDomain || isLoading}
|
||||
>
|
||||
Check Availability
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
// add delay to namehash computation / getting the availability
|
||||
private onChange = (event: React.FormEvent<HTMLButtonElement>) => {
|
||||
const domainToCheck = event.currentTarget.value.toLowerCase().trim();
|
||||
const isValidDomain = isValidENSName(domainToCheck);
|
||||
this.setState({
|
||||
domainToCheck,
|
||||
isValidDomain
|
||||
});
|
||||
};
|
||||
|
||||
private onSubmit = (ev: React.FormEvent<HTMLElement>) => {
|
||||
ev.preventDefault();
|
||||
const { isValidDomain, domainToCheck } = this.state;
|
||||
return isValidDomain && this.props.resolveDomainRequested(domainToCheck);
|
||||
};
|
||||
|
||||
private onFocus = () => this.setState({ isFocused: true });
|
||||
private onBlur = () => this.setState({ isFocused: false });
|
||||
}
|
||||
|
||||
function mapStateToProps(state: AppState) {
|
||||
return {
|
||||
domainRequests: state.ens.domainRequests
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
resolveDomainRequested
|
||||
})(NameInput);
|
|
@ -1,39 +0,0 @@
|
|||
import React from 'react';
|
||||
import NameInputHoc from './NameInputHOC';
|
||||
|
||||
interface Props {
|
||||
isValidDomain: boolean;
|
||||
domainToCheck: string;
|
||||
onClick(ev: React.FormEvent<HTMLButtonElement>): void;
|
||||
onChange(ev: React.FormEvent<HTMLInputElement>): void;
|
||||
}
|
||||
class ENSNameInput extends React.Component<Props, {}> {
|
||||
public render() {
|
||||
const { onChange, onClick, isValidDomain, domainToCheck } = this.props;
|
||||
return (
|
||||
<article className="row">
|
||||
<section className="col-xs-12 col-sm-6 col-sm-offset-3 text-center">
|
||||
<div className="input-group">
|
||||
<input
|
||||
className={`form-control ${
|
||||
domainToCheck === '' ? '' : isValidDomain ? 'is-valid' : 'is-invalid'
|
||||
}`}
|
||||
type="text"
|
||||
placeholder="myetherwallet"
|
||||
onChange={onChange}
|
||||
/>
|
||||
<div className="input-group-btn">
|
||||
<a className="btn btn-default">.eth</a>
|
||||
</div>
|
||||
</div>
|
||||
{isValidDomain ? null : <p>Use at least 7 characters</p>}
|
||||
<button className="btn btn-primary " onClick={onClick}>
|
||||
Check ENS Name
|
||||
</button>
|
||||
</section>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NameInputHoc(ENSNameInput);
|
|
@ -1,42 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
|
||||
import { isValidENSName } from 'libs/validators';
|
||||
interface State {
|
||||
domainToCheck: string;
|
||||
isValidDomain: boolean;
|
||||
}
|
||||
interface Props {
|
||||
resolveDomainRequested(domain: string): void;
|
||||
}
|
||||
|
||||
const NameInputHoc = PassedComponent =>
|
||||
class HOC extends Component<Props, State> {
|
||||
public state = {
|
||||
isValidDomain: false,
|
||||
domainToCheck: ''
|
||||
};
|
||||
//add delay to namehash computation / getting the availability
|
||||
public onChange = (event: React.FormEvent<HTMLButtonElement>) => {
|
||||
const domainToCheck: string = event.currentTarget.value.toLowerCase();
|
||||
this.setState({ domainToCheck });
|
||||
const isValidName: boolean = isValidENSName(domainToCheck);
|
||||
this.setState({ isValidDomain: isValidName });
|
||||
};
|
||||
public onClick = () => {
|
||||
const { isValidDomain, domainToCheck } = this.state;
|
||||
const { resolveDomainRequested } = this.props;
|
||||
return isValidDomain && resolveDomainRequested(domainToCheck);
|
||||
};
|
||||
public render() {
|
||||
const { onChange, onClick } = this;
|
||||
const { isValidDomain, domainToCheck } = this.state;
|
||||
const props = {
|
||||
onChange,
|
||||
onClick,
|
||||
isValidDomain,
|
||||
domainToCheck
|
||||
};
|
||||
return <PassedComponent {...props} />;
|
||||
}
|
||||
};
|
||||
export default NameInputHoc;
|
|
@ -1 +0,0 @@
|
|||
export { default as NameInput } from './components/NameInput';
|
|
@ -1,19 +1,30 @@
|
|||
.auction-info {
|
||||
margin-bottom: 32px;
|
||||
@import 'common/sass/variables';
|
||||
|
||||
.NameResolve {
|
||||
&-loader {
|
||||
text-align: center;
|
||||
padding: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ens-title {
|
||||
margin: 2rem 0;
|
||||
margin: 0 0 1.5rem;
|
||||
h2 {
|
||||
margin: 0;
|
||||
line-height: 2.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ens-panel-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
.ens-panel {
|
||||
flex-grow: 1;
|
||||
max-width: 540px;
|
||||
min-width: 360px;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
background-color: #185475;
|
||||
|
@ -23,14 +34,14 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
&-light {
|
||||
&.is-light {
|
||||
background-color: #1e92ba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
overflow-y: scroll;
|
||||
.ens-table-wrapper {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { IBaseDomainRequest } from 'libs/ens';
|
|||
import ENSTime from './components/ENSTime';
|
||||
import moment from 'moment';
|
||||
import { NewTabLink } from 'components/ui';
|
||||
import { ensV3Url } from 'utils/formatters';
|
||||
|
||||
const getDeadlines = (registrationDate: string) => {
|
||||
// Get the time to reveal bids, and the time when the action closes
|
||||
|
@ -28,15 +29,19 @@ export const NameAuction: React.SFC<IBaseDomainRequest> = props => {
|
|||
<section className="ens-panel">
|
||||
<ENSTime text="Reveal Bids On" time={revealBidTime} />
|
||||
</section>
|
||||
<section className="ens-panel ens-panel-light">
|
||||
<section className="ens-panel is-light">
|
||||
<ENSTime text="Auction Closes On" time={auctionCloseTime} />
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<NewTabLink
|
||||
content={`Do you want to place a bid on ${name}.eth? You'll need to bid on MyCrypto V3 by clicking here: `}
|
||||
href="https://mycrypto.com/#ens"
|
||||
/>
|
||||
<p>
|
||||
Do you want to place a bid on {name}.eth?{' '}
|
||||
<strong>
|
||||
<NewTabLink href={ensV3Url(name)}>
|
||||
You can do that on MyCrypto V3 by clicking here!
|
||||
</NewTabLink>
|
||||
</strong>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
import React from 'react';
|
||||
import { IBaseDomainRequest } from 'libs/ens';
|
||||
import { NewTabLink } from 'components/ui';
|
||||
import { ensV3Url } from 'utils/formatters';
|
||||
|
||||
export const NameOpen: React.SFC<IBaseDomainRequest> = props => (
|
||||
<section className="row">
|
||||
<section className="auction-info text-center">
|
||||
<div className="ens-title">
|
||||
<h1>
|
||||
<strong>{props.name}.eth</strong> is available!
|
||||
<strong>{props.name}.eth</strong> is available
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<NewTabLink
|
||||
className="text-center"
|
||||
content={`Do you want ${
|
||||
props.name
|
||||
}.eth? You'll need open an auction on MyCrypto V3 by clicking here`}
|
||||
href="https://mycrypto.com/#ens"
|
||||
/>
|
||||
<p>
|
||||
Do you want {props.name}.eth?{' '}
|
||||
<strong>
|
||||
<NewTabLink className="text-center" href={ensV3Url(props.name)}>
|
||||
Open an auction on MyCrypto v3!
|
||||
</NewTabLink>
|
||||
</strong>
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@ export const NameOwned: React.SFC<IOwnedDomainRequest> = ({
|
|||
<strong>{name}.eth</strong> is already owned
|
||||
</h1>
|
||||
</div>
|
||||
<div className="table-wrapper">
|
||||
<div className="ens-table-wrapper">
|
||||
<table className="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
|
|
@ -3,17 +3,16 @@ import { IRevealDomainRequest } from 'libs/ens';
|
|||
import ENSTime from './components/ENSTime';
|
||||
import { UnitDisplay, NewTabLink } from 'components/ui';
|
||||
import { Wei } from 'libs/units';
|
||||
import { ensV3Url } from 'utils/formatters';
|
||||
|
||||
export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
||||
<section className="row text-center">
|
||||
<div className="auction-info text-center">
|
||||
<div className="ens-title">
|
||||
<h2>
|
||||
<p>
|
||||
It's time to reveal the bids for <strong>{props.name}.eth.</strong>{' '}
|
||||
</p>
|
||||
<p>
|
||||
Current Highest bid is{' '}
|
||||
It's time to reveal the bids for <strong>{props.name}.eth</strong>
|
||||
<br />
|
||||
The current highest bid is{' '}
|
||||
<strong>
|
||||
<UnitDisplay
|
||||
value={Wei(props.highestBid)}
|
||||
|
@ -23,7 +22,6 @@ export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
|||
checkOffline={false}
|
||||
/>
|
||||
</strong>
|
||||
</p>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
|
@ -33,11 +31,14 @@ export const NameReveal: React.SFC<IRevealDomainRequest> = props => (
|
|||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<NewTabLink
|
||||
content={`Did you you bid on ${
|
||||
props.name
|
||||
}.eth? You must reveal your bid now. You'll need reveal your bid on MyCrypto V3 by clicking here`}
|
||||
href="https://mycrypto.com/#ens"
|
||||
/>
|
||||
|
||||
<p>
|
||||
Did you bid on {props.name}.eth? You must reveal your bid now.{' '}
|
||||
<strong>
|
||||
<NewTabLink href={ensV3Url(props.name)}>
|
||||
You can do that on MyCrypto v3 by clicking here!
|
||||
</NewTabLink>
|
||||
</strong>
|
||||
</p>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -6,53 +6,46 @@ interface Props {
|
|||
}
|
||||
|
||||
interface State {
|
||||
currentTime: number;
|
||||
timeDisplay: string;
|
||||
}
|
||||
|
||||
class CountDown extends Component<Props, State> {
|
||||
public state = { currentTime: 0 };
|
||||
public state = { timeDisplay: '' };
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
public componentDidMount() {
|
||||
this.startCountDown();
|
||||
this.state = { currentTime: 0 };
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { currentTime } = this.state;
|
||||
return <p>{this.humanizeTime(currentTime)}</p>;
|
||||
return <p>{this.state.timeDisplay}</p>;
|
||||
}
|
||||
|
||||
private humanizeTime = (time: number) => {
|
||||
let timeRemaining = time;
|
||||
const floorTime = unit => Math.floor(timeRemaining / unit);
|
||||
const pad = (num: number) => num.toString().padStart(2, '0');
|
||||
const second = 1000;
|
||||
const minute = second * 60;
|
||||
const hour = minute * 60;
|
||||
const day = hour * 24;
|
||||
|
||||
const days = floorTime(day);
|
||||
timeRemaining -= days * day;
|
||||
const hours = floorTime(hour);
|
||||
timeRemaining -= hours * hour;
|
||||
const minutes = floorTime(minute);
|
||||
timeRemaining -= minutes * minute;
|
||||
const seconds = floorTime(second);
|
||||
|
||||
return `${pad(days)} Days ${pad(hours)} Hours ${pad(minutes)} Minutes ${pad(seconds)} Seconds `;
|
||||
};
|
||||
|
||||
private startCountDown = () => {
|
||||
const intervalId = window.setInterval(() => {
|
||||
const nextTime = +moment(this.props.initialTime).diff(+moment(), 'ms');
|
||||
const time = moment(this.props.initialTime);
|
||||
let intervalId;
|
||||
|
||||
if (nextTime < 0) {
|
||||
return clearInterval(intervalId);
|
||||
const setTimeDisplay = () => {
|
||||
const diff = moment.duration(time.diff(moment()));
|
||||
let timeDisplay;
|
||||
|
||||
if (diff) {
|
||||
const pieces = [
|
||||
diff.days() > 0 && `${diff.days()} days`,
|
||||
diff.hours() > 0 && `${diff.hours()} hours`,
|
||||
diff.minutes() > 0 && `${diff.minutes()} minutes`,
|
||||
diff.seconds() > 0 && `${diff.seconds()} seconds`
|
||||
].filter(piece => !!piece);
|
||||
timeDisplay = `in ${pieces.join(', ')}`;
|
||||
} else {
|
||||
clearInterval(intervalId);
|
||||
timeDisplay = 'Auction is over!';
|
||||
}
|
||||
|
||||
this.setState({ currentTime: nextTime });
|
||||
}, 1000);
|
||||
this.setState({ timeDisplay });
|
||||
};
|
||||
|
||||
intervalId = setInterval(setTimeDisplay, 1000);
|
||||
setTimeDisplay();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -62,9 +55,9 @@ interface ITime {
|
|||
}
|
||||
|
||||
const ENSTime: React.SFC<ITime> = ({ text, time }) => (
|
||||
<section className="sm-6 col-xs-12 order-info">
|
||||
<section>
|
||||
<p>{text}</p>
|
||||
<h4>{moment(time).toString()}</h4>
|
||||
<h4>{moment(time).format('LLLL')}</h4>
|
||||
<CountDown initialTime={time} />
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from 'reducers';
|
||||
import { NameState } from 'libs/ens';
|
||||
import {
|
||||
|
@ -9,8 +10,8 @@ import {
|
|||
NameOpen,
|
||||
NameReveal
|
||||
} from './components';
|
||||
import './NameResolve.scss';
|
||||
import { Spinner } from 'components/ui';
|
||||
import './NameResolve.scss';
|
||||
|
||||
type Props = AppState['ens'];
|
||||
|
||||
|
@ -23,7 +24,7 @@ const modeResult = {
|
|||
[NameState.Reveal]: NameReveal
|
||||
};
|
||||
|
||||
export const NameResolve: React.SFC<Props> = props => {
|
||||
const NameResolve: React.SFC<Props> = props => {
|
||||
const { domainRequests, domainSelector } = props;
|
||||
const { currentDomain } = domainSelector;
|
||||
|
||||
|
@ -32,7 +33,20 @@ export const NameResolve: React.SFC<Props> = props => {
|
|||
}
|
||||
|
||||
const domainData = domainRequests[currentDomain].data! || false;
|
||||
const Component = domainData ? modeResult[domainData.mode] : Spinner;
|
||||
let content;
|
||||
|
||||
return <Component {...domainData} />;
|
||||
if (domainData) {
|
||||
const Component = modeResult[domainData.mode];
|
||||
content = <Component {...domainData} />;
|
||||
} else {
|
||||
content = (
|
||||
<div className="NameResolve-loader">
|
||||
<Spinner size="x3" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div className="Tab-content-pane">{content}</div>;
|
||||
};
|
||||
|
||||
export default connect((state: AppState): Props => ({ ...state.ens }))(NameResolve);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export { GeneralInfoPanel } from './GeneralInfoPanel';
|
||||
export { NameInput } from './NameInput';
|
||||
export { NameResolve } from './NameResolve';
|
||||
export { default as GeneralInfoPanel } from './GeneralInfoPanel';
|
||||
export { default as NameInput } from './NameInput';
|
||||
export { default as NameResolve } from './NameResolve';
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
@import 'common/sass/variables';
|
||||
|
||||
.ENS {
|
||||
&-title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-description {
|
||||
max-width: 800px;
|
||||
margin: 0 auto $space;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,9 @@
|
|||
import React from 'react';
|
||||
import { GeneralInfoPanel, NameInput, NameResolve } from './components';
|
||||
import { NameInput, NameResolve } from './components';
|
||||
import TabSection from 'containers/TabSection';
|
||||
import { Route, Switch, RouteComponentProps } from 'react-router';
|
||||
import { RouteNotFound } from 'components/RouteNotFound';
|
||||
import { NewTabLink } from 'components/ui';
|
||||
import { donationAddressMap } from 'config';
|
||||
import translate from 'translations';
|
||||
import { connect } from 'react-redux';
|
||||
import { resolveDomainRequested, TResolveDomainRequested } from 'actions/ens';
|
||||
import { AppState } from 'reducers';
|
||||
import './index.scss';
|
||||
|
||||
const ENSDocsLink = () => (
|
||||
<NewTabLink
|
||||
|
@ -17,57 +12,28 @@ const ENSDocsLink = () => (
|
|||
/>
|
||||
);
|
||||
|
||||
const ENSTitle = () => (
|
||||
<article className="cont-md">
|
||||
<h1 className="text-center">{translate('NAV_ENS')}</h1>
|
||||
<p>
|
||||
The <ENSDocsLink /> is a distributed, open, and extensible naming system based on the Ethereum
|
||||
blockchain. Once you have a name, you can tell your friends to send ETH to{' '}
|
||||
<code>ensdomain.eth</code> instead of
|
||||
<code>{donationAddressMap.ETH.substr(0, 12)}...</code>
|
||||
</p>
|
||||
</article>
|
||||
);
|
||||
|
||||
interface StateProps {
|
||||
ens: AppState['ens'];
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
resolveDomainRequested: TResolveDomainRequested;
|
||||
}
|
||||
|
||||
type Props = StateProps & DispatchProps;
|
||||
|
||||
class ENSClass extends React.Component<RouteComponentProps<any> & Props> {
|
||||
export default class ENSClass extends React.Component<{}> {
|
||||
public render() {
|
||||
const { match } = this.props;
|
||||
const currentPath = match.url;
|
||||
return (
|
||||
<TabSection isUnavailableOffline={true}>
|
||||
<section className="container">
|
||||
<Switch>
|
||||
<Route
|
||||
exact={true}
|
||||
path={currentPath}
|
||||
render={() => (
|
||||
<section role="main" className="row">
|
||||
<ENSTitle />
|
||||
<NameInput resolveDomainRequested={this.props.resolveDomainRequested} />
|
||||
<NameResolve {...this.props.ens} />
|
||||
<GeneralInfoPanel />
|
||||
</section>
|
||||
)}
|
||||
/>
|
||||
<RouteNotFound />
|
||||
</Switch>
|
||||
<div className="Tab-content">
|
||||
<section className="Tab-content-pane">
|
||||
<div className="ENS">
|
||||
<h1 className="ENS-title">Ethereum Name Service</h1>
|
||||
<p className="ENS-description">
|
||||
The <ENSDocsLink /> is a distributed, open, and extensible naming system based on
|
||||
the Ethereum blockchain. Once you have a name, you can tell your friends to send ETH
|
||||
to <code>ensdomain.eth</code> instead of
|
||||
<code>{donationAddressMap.ETH.substr(0, 12)}...</code>
|
||||
</p>
|
||||
|
||||
<NameInput />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<NameResolve />
|
||||
</div>
|
||||
</TabSection>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState): StateProps => ({ ens: state.ens });
|
||||
const mapDispatchToProps: DispatchProps = { resolveDomainRequested };
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ENSClass);
|
||||
|
|
|
@ -47,7 +47,7 @@ function* resolveDomain(): SagaIterator {
|
|||
|
||||
const result: { domainData: IBaseDomainRequest; error } = yield race({
|
||||
domainData: call(resolveDomainRequest, domain, node),
|
||||
err: call(delay, 4000)
|
||||
err: call(delay, 10000)
|
||||
});
|
||||
|
||||
const { domainData } = result;
|
||||
|
|
|
@ -109,3 +109,7 @@ export function bytesToHuman(bytes: number) {
|
|||
const i = Math.round(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||
return Math.round(bytes / Math.pow(1024, i)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
export function ensV3Url(name: string) {
|
||||
return `https://mycrypto.com/?ensname=${name}#ens`;
|
||||
}
|
||||
|
|
|
@ -1,45 +1,42 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`snapshot test ENS component 1`] = `
|
||||
<ENSClass
|
||||
history={
|
||||
Object {
|
||||
"action": "PUSH",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 2,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"key": "e08jz7",
|
||||
"pathname": "/ens",
|
||||
"search": "",
|
||||
"state": Object {},
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
}
|
||||
}
|
||||
location={
|
||||
Object {
|
||||
"hash": "",
|
||||
"key": "e08jz7",
|
||||
"pathname": "/ens",
|
||||
"search": "",
|
||||
"state": Object {},
|
||||
}
|
||||
}
|
||||
match={
|
||||
Object {
|
||||
"isExact": false,
|
||||
"params": Object {},
|
||||
"path": "/ens",
|
||||
"url": "/ens",
|
||||
}
|
||||
}
|
||||
resolveDomainRequested={[Function]}
|
||||
/>
|
||||
<Connect(TabSection)
|
||||
isUnavailableOffline={true}
|
||||
>
|
||||
<div
|
||||
className="Tab-content"
|
||||
>
|
||||
<section
|
||||
className="Tab-content-pane"
|
||||
>
|
||||
<div
|
||||
className="ENS"
|
||||
>
|
||||
<h1
|
||||
className="ENS-title"
|
||||
>
|
||||
Ethereum Name Service
|
||||
</h1>
|
||||
<p
|
||||
className="ENS-description"
|
||||
>
|
||||
The
|
||||
<ENSDocsLink />
|
||||
is a distributed, open, and extensible naming system based on the Ethereum blockchain. Once you have a name, you can tell your friends to send ETH to
|
||||
<code>
|
||||
ensdomain.eth
|
||||
</code>
|
||||
instead of
|
||||
<code>
|
||||
0x4bbeEB066e
|
||||
...
|
||||
</code>
|
||||
</p>
|
||||
<Connect(NameInput) />
|
||||
</div>
|
||||
</section>
|
||||
<Connect(NameResolve) />
|
||||
</div>
|
||||
</Connect(TabSection)>
|
||||
`;
|
||||
|
|
Loading…
Reference in New Issue