#60 & #61: UI must handle reserved names; Remove "Already have a Status subdomain?" block from main screen (#63)

This commit is contained in:
Alexander Pantyuhov 2018-10-19 15:33:50 +02:00 committed by GitHub
parent 47c4c6c205
commit 96502db101
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 29 deletions

View File

@ -35,6 +35,7 @@ import { YOUR_CONTACT_CODE } from './constants';
import DisplayBox from './DisplayBox';
import styled from "styled-components";
import { Route } from "react-router-dom";
import { ReservedUsernames } from '../../../config/ens-usernames/reservedNames'
const normalizer = new IDNANormalizer();
const invalidSuffix = '0000000000000000000000000000000000000000'
@ -72,7 +73,7 @@ const pastReleaseDate = timestamp => new Date > new Date(timestamp * 1000);
const MobileAddressDisplay = ({ domainName, address, statusAccount, expirationTime, creationTime, defaultAccount, isOwner, edit, onSubmit, handleChange, values, handleSubmit }) => (
<Fragment>
<LookupForm {...{ handleSubmit, values, handleChange }} />
<LookupForm {...{ handleSubmit, values, handleChange }} warningCanBeDisplayed={false} />
<Info background={isOwner ? '#44D058' : '#000000'} style={{ margin: '0.5em', boxShadow: '0px 6px 10px rgba(0, 0, 0, 0.2)' }}>
<Typography variant="title" style={
{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'space-evenly', height: '4em', color: '#ffffff', textAlign: 'center', margin: '10%' }
@ -287,9 +288,23 @@ const DisplayAddress = connect(mapStateToProps)((props) => (
</Fragment>
));
class WarningBlock extends React.Component {
render() {
const { status } = this.props;
if (status && status.domainNameStatus === DomainNameStatus.InvalidName) {
return <Warning>Names are made with<br/>letters and numbers only</Warning>
}
else if (status) {
return <Warning>This name is reserved for security purposes. Please try another.</Warning>
}
return null;
}
}
class LookupForm extends React.Component {
render() {
const { handleSubmit, values, handleChange, isWarningDisplayed } = this.props;
const { handleSubmit, values, handleChange, warningCanBeDisplayed } = this.props;
return (
<Fragment>
@ -306,14 +321,13 @@ class LookupForm extends React.Component {
</Hidden>
<Hidden mdUp>
<MobileSearch
search
name="domainName"
placeholder='Search for available name'
value={values.domainName}
onChange={handleChange}
required
wide/>
{isWarningDisplayed && <Warning>Names are made with<br/>letters and numbers only</Warning>}
{warningCanBeDisplayed && <WarningBlock {...this.props} />}
</Hidden>
<Hidden mdDown>
<Button mode="strong" type="submit" style={{marginLeft: '3%', maxWidth: '95%'}} wide>
@ -326,11 +340,24 @@ class LookupForm extends React.Component {
}
}
const isValidDomainName = val => /^([a-z0-9]+)$/.test(val.toLowerCase());
const DomainNameStatus = Object.freeze({"Correct": 1, "InvalidName": 2, "ReservedName": 3});
const getDomainNameStatus = val => {
const value = val.toLowerCase().trim();
if (/^([a-z0-9]+)$/.test(value)) {
if (ReservedUsernames.includes(value)) {
return DomainNameStatus.ReservedName;
}
return DomainNameStatus.Correct;
} else {
return DomainNameStatus.InvalidName;
}
}
class SearchResultsPage extends React.Component {
async loadDomainInformation({setStatus, domainName}) {
if (isValidDomainName(domainName)) {
const status = getDomainNameStatus(domainName);
if (status === DomainNameStatus.Correct) {
const { methods: { owner, resolver } } = ENSRegistry;
const lookupHash = hash(formatName(domainName));
const subdomainHash = soliditySha3(domainName);
@ -359,7 +386,7 @@ class SearchResultsPage extends React.Component {
});
});
} else {
setStatus({isInvalidDomain: true });
setStatus({domainNameStatus: status });
}
}
@ -402,7 +429,7 @@ class SearchResultsPage extends React.Component {
return (
<div>
{!status || !status.address ?
<LookupForm {...this.props} isWarningDisplayed={status && status.isInvalidDomain}/>
<LookupForm {...this.props} warningCanBeDisplayed={true}/>
:
validAddress(status.address) || defaultAccount === status.ownerAddress ?
<DisplayAddress
@ -415,7 +442,7 @@ class SearchResultsPage extends React.Component {
registryOwnsDomain={status.registryOwnsDomain}
setStatus={setStatus}/> :
<div>
<LookupForm {...this.props} isWarningDisplayed={false}/>
<LookupForm {...this.props} warningCanBeDisplayed={false}/>
<ConnectedRegister
style={{position: 'relative'}}
setStatus={setStatus}
@ -447,7 +474,7 @@ class NameLookupContainer extends React.Component {
<Route
exact
path={match.url}
render={() => <LookupForm {...this.props} isWarningDisplayed={status && status.isInvalidDomain}/>}/>
render={() => <LookupForm {...this.props} warningCanBeDisplayed={true}/>}/>
<Route
path={`${match.url}/:domainName`}
render={({match}) => <SearchResultsPage {...this.props} match={match}/>}/>

View File

@ -90,11 +90,3 @@
color: #adb5bd;
line-height: 1.313rem;
}
.ens-welcome__info {
border-top: solid 1px #ccc;
border-bottom: solid 1px #ccc;
margin: 30px 0 20px;
padding: 15px 0;
text-align: center;
}

View File

@ -41,7 +41,6 @@ const WelcomeContent = () => (
<div className="text">Share your name to chat on Status or receive ETH and tokens.</div>
</li>
</ol>
<div className="ens-welcome__info">Already have a Status subdomain? <a href="">Manage it</a></div>
<div className="text-light">
<small>Powered by Ethereum Name Services</small>
</div>

View File

@ -16,11 +16,17 @@ const searchWrapper = {
boxSizing: 'border-box',
};
const pasteStyle = {
...searchWrapper,
paddingLeft: '17em',
color: theme.accent
};
const SearchWrapper = styled.div`
width: 100%;
height: 100%;
position: absolute;
pointer-events: none;
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 11px;
box-sizing: border-box;
`;
const MobileInput = styled.input`
display: block;
@ -33,20 +39,20 @@ const MobileInput = styled.input`
appearance: none;
box-shadow: none;
padding-left: ${({ search }) => (search ? '45px' : '15px')};
&:focus {
outline: none;
border-color: ${theme.contentBorderActive};
outline: none;
border-color: ${theme.contentBorderActive};
}
`;
const MobileSearch = props => (
<div style={{ position: 'relative' }}>
{props.search && <div style={searchWrapper}>
{props.search && <SearchWrapper>
<SearchIcon style={{ color: theme.accent }} />
</div>}
</SearchWrapper>}
<div style={{ display: 'flex' }}>
<MobileInput {...props} autoCapitalize="none" />
{!props.value && props.paste && <Button style={{ color: theme.accent }} onClick={props.paste}>Paste</Button>}
</div>
</div>
);