A Pen by Edwin Clement on CodePen.
Created
August 15, 2020 15:33
-
-
Save edwinclement08/93cceb800fe0b8403edd2b98efc89d48 to your computer and use it in GitHub Desktop.
Email Regex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="app"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// normally these would be `import` statements bundled by webpack | |
const { React } = window; | |
const { ReactDOM } = window; | |
colors = [ "#aed581", "#fff59d", "#CCFFFF", "#CCCCFF", "#FFCC00", "#FF9999", | |
"#669999", "#FFFF66", "#e91e63", "#e65722", "#b8860b", "#009fd4" ]; | |
mapping = {}; | |
const EmailBox = ({ email, state }) => { | |
domain = email.split("@")[1]; | |
color = mapping[domain]; | |
style = {}; | |
if (state == "discarded") { | |
stateClass = "discarded"; | |
} else if (state == "chosen") { | |
stateClass = "chosen"; | |
} else { | |
stateClass = "unprocessed"; | |
style = { backgroundColor: color }; | |
} | |
return ( | |
<span | |
className={`emailbox ${stateClass}`} | |
style={style} | |
> | |
{email} | |
</span> | |
); | |
}; | |
const DomainBox = ({ domain }) => { | |
color = mapping[domain]; | |
return ( | |
<span className="domainbox" style={{ backgroundColor: color }}> | |
{domain} | |
</span> | |
); | |
}; | |
const validateEmail = (email) => email.indexOf('@') > 0 && email.indexOf('.') > 0; | |
const validateDomain = (domain) => domain.indexOf('@') == -1 && domain.indexOf('.') > 0; | |
const App = () => { | |
const [chosen, setChosen] = React.useState(false); | |
const [emailList, setEmailList] = React.useState([ | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" }, | |
{ email: "[email protected]", state: "unprocessed" } | |
]); | |
const [freeDomainList, setFreeDomainList] = React.useState([ | |
"yahoo.com", "gmail.com", "outlook.com" | |
]); | |
const [domainsToProcess, setDomainsToProcess] = React.useState([]); | |
const [input, setInput] = React.useState({}) | |
const handleInputChange = (e) => setInput({ | |
...input, | |
[e.currentTarget.name]: e.currentTarget.value | |
}) | |
const handleEnter = (e) => { | |
if (e.key !== 'Enter') return | |
if (e.currentTarget.name == 'emailToAdd') { | |
email = e.currentTarget.value; | |
if(validateEmail(email)) { | |
setInput({...input,[e.currentTarget.name]: ''}) | |
setEmailList([{email, status: 'unprocessed'}, ...emailList]); | |
} | |
else alert("Email entered is invalid.") | |
} else if (e.currentTarget.name == 'domainToAdd') { | |
domain = e.currentTarget.value; | |
if(validateDomain(domain)){ | |
newInput = {...input, [e.currentTarget.name]: ''} | |
setInput(newInput) | |
console.log(newInput) | |
newList = [domain, ...freeDomainList] | |
setFreeDomainList(newList); | |
setDomainsToProcess(newList); | |
regex = '(' + newList.map(x => escapeChars(x)).join('|') + ')$'; | |
setRegexOverride(regex); | |
setGenRegex(regex); | |
} | |
else alert("Domain entered is invalid.") | |
} | |
} | |
emailList.forEach(x => { | |
domain = x.email.split("@")[1]; | |
color = mapping[domain]; | |
color ||= colors.pop(); | |
mapping[domain] = color; | |
}); | |
React.useEffect(() => { | |
regex = '(' + freeDomainList.map(x => escapeChars(x)).join('|') + ')$'; | |
setGenRegex(regex); | |
setRegexOverride(regex); | |
setDomainsToProcess(freeDomainList); | |
},[]) | |
const emailBoxes = emailList.map((x) => ( | |
<EmailBox email={x.email} state={x.state} /> | |
)); | |
selectedDomain = freeDomainList[0]; | |
const domainList = freeDomainList.map((x) => ( | |
<DomainBox domain={x} selected={selectedDomain == x} /> | |
)); | |
const [genRegex, setGenRegex] = React.useState(''); | |
const [regexOverride, setRegexOverride] = React.useState(''); | |
const overwrite = ({currentTarget: {value}}) => setRegexOverride(value); | |
const applyRegex = () => { | |
const matches = emailList.filter((e) => e.email.match(new RegExp(regexOverride, 'g'))); | |
setEmailList(emailList.map((info) => { | |
if (matches.map(x => x.email).indexOf(info.email) >= 0) { | |
return { email: info.email, state: 'discarded'} | |
} | |
return info; | |
})); | |
} | |
const resetEmailState = () => { | |
setEmailList(emailList.map((info) => { | |
return { email: info.email, state: 'unprocessed'} | |
})); | |
setRegexOverride(genRegex); | |
setDomainsToProcess(freeDomainList); | |
} | |
escapeChars = (r) => r.replace('.','\\.') | |
const [method, setMethod] = React.useState('regex') // '' regex | |
const methodClick = ({currentTarget: {value}}) => { setMethod(value); resetEmailState(); } | |
if (method == 'find') { | |
domain = domainsToProcess[0]; | |
displayList = freeDomainList.map(domain => { | |
style = {} | |
if (domainsToProcess.indexOf(domain) >= 0) { | |
style.backgroundColor = mapping[domain] | |
} else { | |
style.backgroundColor = 'black'; | |
style.color = 'white'; | |
} | |
return <div className='findDomainStep' style={style}>{domain}</div> | |
}); | |
const removeDomain = () => { | |
domain = domainsToProcess[0]; | |
if (domain == undefined) return; | |
setEmailList(emailList.map((info) => { | |
if(info.email.indexOf(domain) >= 0) { | |
return { email: info.email, state: 'discarded' }; | |
} | |
return info; | |
})); | |
setDomainsToProcess(domainsToProcess.filter(d => d !== domain)); | |
} | |
stepCount = freeDomainList.length - domainsToProcess.length ; | |
finshedSteps = domainsToProcess.length == 0; | |
controls = ( | |
<div> | |
<div className="explanation"> | |
<h3>Explanation</h3> | |
<p style={{maxWidth: '20rem'}}> | |
As mentioned before, we need to step through the free domains list: ["{freeDomainList.join('", "')}"]. For each domain, we will | |
remove the corresponding emails. | |
<h4>Steps</h4> | |
{ | |
finshedSteps ? | |
<div> | |
{stepCount + 1} Finished the email shortlisting!! | |
</div> | |
: | |
<div> | |
{stepCount+1}. Remove all emails from the domain '{domainsToProcess[0]}' by clicking on the button <b>Remove: {domainsToProcess[0]}</b> | |
</div> | |
} | |
</p> | |
</div> | |
<div className="processor"> | |
<h3>Domains to Process</h3> | |
<div> | |
{displayList} | |
</div> | |
<div className='method-buttons'> | |
<input id='next-step-regex' type='button' value={finshedSteps ? "Finished" : `Remove: ${domain}`} disabled={finshedSteps} onClick={removeDomain}/> | |
<input id='reset-find' type='button' value='Reset Process' onClick={resetEmailState}/> | |
</div> | |
</div> | |
</div>); | |
} else { | |
controls = ( | |
<div> | |
<div className="explanation"> | |
<h3>Explanation</h3> | |
<p > | |
In Regex its quite simple, you need to generate the appropriate regex. For the given domains, it is: | |
<br/> | |
<br/> | |
<span className='regexholder'> | |
{genRegex} | |
</span> | |
<h4>Steps</h4> | |
<ol> | |
<li> | |
Use the above Regex, with the match function. In Javascript, it looks like this: | |
<pre> | |
email.match(/regex/) | |
</pre> | |
This will tell if the email is from any given domain, in one shot. | |
</li> | |
<li>Discard any email that returns true for the above expression.</li> | |
<li>That's it.</li> | |
</ol> | |
</p> | |
</div> | |
<div className="processor"> | |
<i>Enter Your Custom Regex to Override</i> | |
<br/> | |
<input id='regex-override' value={regexOverride} onChange={overwrite}/> | |
<br/> | |
<br/> | |
<div className='method-buttons'> | |
<input id='apply-regex' type='button' value='Apply Regex' onClick={applyRegex}/> | |
<input id='reset-regex' type='button' value='Reset Regex' onClick={resetEmailState}/> | |
</div> | |
</div> | |
</div>); | |
} | |
return ( | |
<div className="mainContainer"> | |
<div className="emailContainer"> | |
<span id="EmailTitle">Emails</span> | |
<input className='input-boxes' type="text" placeholder="Email to Add" name="emailToAdd" | |
onChange={handleInputChange} onKeyDown={handleEnter} value={input.emailToAdd} | |
/> | |
{emailBoxes} | |
</div> | |
<div className="domainContainer"> | |
<span id="DomainTitle">Free Domains</span> | |
<input className='input-boxes' type="text" placeholder="Domain to Add" name="domainToAdd" | |
onChange={handleInputChange} onKeyDown={handleEnter} value={input.domainToAdd} | |
/> | |
{domainList} | |
</div> | |
<div className="controlContainer"> | |
<div className='methodRadio'> | |
<div> | |
<input type="radio" id="male" name="method" onClick={methodClick} checked={method == 'find'} value="find"/> | |
{' '} | |
<label for="male">Find</label> | |
</div> | |
<div> | |
<input type="radio" id="female" name="method" onClick={methodClick} checked={method == 'regex'} value="regex"/> | |
{' '} | |
<label for="female">Regex</label> | |
</div> | |
</div> | |
{controls} | |
</div> | |
</div> | |
); | |
}; | |
ReactDOM.render(<App />, document.getElementById("app")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.2/umd/react.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.2/umd/react-dom.production.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.mainContainer { | |
display: grid; | |
padding-top: 1rem; | |
grid-template-areas: | |
". . . . . . ." | |
". emails . domain . contrl ." | |
". . . . . . ." | |
; | |
.input-boxes { | |
margin: 0.5rem; | |
border-radius: 5px; | |
} | |
.emailContainer { | |
display: flex; | |
flex-direction: column; | |
grid-area: emails; | |
#EmailTitle{ | |
font-weight: bold; | |
margin: 0.5rem 0 0.5rem 0.5rem; | |
} | |
.emailbox { | |
padding: 5px; | |
display: inline-block; | |
border-radius: 5px; | |
margin: 0 0 0.5rem 0.5rem; | |
&.discarded { | |
background: black; | |
} | |
} | |
} | |
.domainContainer { | |
display: flex; | |
flex-direction: column; | |
grid-area: domain; | |
#DomainTitle { | |
font-weight: bold; | |
margin: 0.5rem 0 0.5rem 0.5rem; | |
} | |
.domainbox { | |
padding: 5px; | |
display: inline-block; | |
border-radius: 5px; | |
margin: 0 0 0.5rem 0.5rem; | |
} | |
} | |
.controlContainer { | |
padding: 1em; | |
grid-area: contrl; | |
border: thin grey solid; | |
border-radius: 5px; | |
.methodRadio { | |
display: flex; | |
justify-content: space-around; | |
} | |
.regexholder { | |
border-radius: 5px; | |
padding: 4px; | |
background: lightgreen; | |
margin: 4px; | |
} | |
#regex-override { | |
width: 90%; | |
margin: auto; | |
border-radius: 5px; | |
} | |
.method-buttons { | |
display: flex; | |
justify-content: space-around; | |
} | |
.findDomainStep { | |
display: block; | |
border: thin black dashed ; | |
padding: 5px; | |
margin-bottom: 10px; | |
} | |
.explanation { | |
max-width: 20rem; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment