Skip to content

Instantly share code, notes, and snippets.

@edwinclement08
Created August 15, 2020 15:33
Show Gist options
  • Save edwinclement08/93cceb800fe0b8403edd2b98efc89d48 to your computer and use it in GitHub Desktop.
Save edwinclement08/93cceb800fe0b8403edd2b98efc89d48 to your computer and use it in GitHub Desktop.
Email Regex
<div id="app"></div>
// 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"));
<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>
.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