Email subscription works and better notification of errors

This commit is contained in:
ポール ウェッブ 2018-07-27 13:04:05 -05:00
parent f856943c01
commit 9168b2e38a
8 changed files with 147 additions and 27 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
/* global $, location, window */ "use strict";
/* global $, location, send, window */ "use strict";
@ -24,6 +24,10 @@ document.querySelector("#close-alert").onclick = function () {
document.querySelector("#alert-beta").style.display = "none";
};
// Smooth scroll
document.querySelectorAll("a[href^='#']").forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
@ -38,6 +42,22 @@ document.querySelectorAll("a[href^='#']").forEach(anchor => {
});
});
// Newsletter
$("[data-action='subscribe to newsletter']").on("click", () => {
const email = $("#emailAddress").val();
if (!validateEmail(email)) return;
send(JSON.stringify({
"email": email,
"message": "subscribe"
}));
});
// H E L P E R S
function scrollToElementOnLoad() {
if (window.location.href.includes("#")) {
setTimeout(() => { // give page time to breathe
@ -51,3 +71,8 @@ function scrollToElementOnLoad() {
}, 150);
}
}
function validateEmail(email) {
const re = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\\.,;:\s@"]{2,})$/i;
return re.test(String(email));
}

View file

@ -12,6 +12,7 @@ ws.onmessage = socket => {
switch (true) {
case data.message === "updated html":
$(data.selector).html(data.html);
$("#emailMessage").val("");
break;
case data.message === "notification": // TODO: Make work with appending so multiple notifications can be sent

View file

@ -116,6 +116,12 @@
.newsletter-cta__message {
@include clearfix;
color: $red;
padding-top: 1rem;
background-color: $teal;
color: $white;
font-size: 1rem;
text-align: center;
&:not(:empty) {
padding: 1rem;
}
}

115
server.js
View file

@ -43,7 +43,11 @@ if (typeof process.env.REDISCLOUD_URL !== "undefined") {
client.on("error", redisError => {
process.env.NODE_ENV === "development" ?
log(`\n${color.yellow("Unable to connect to Redis client.")}\nYou may be missing an .env file or your connection was reset.`) :
logSlackError("An error occured with Redis", redisError)
logSlackError(
"\n" +
"> *REDIS ERROR:* ```" + JSON.parse(JSON.stringify(redisError)) + "```" + "\n" +
"> _Cause: Someone is trying to run LBRY.tech locally without environment variables OR Heroku is busted_\n"
)
;
});
} else log(`${color.red("[missing]")} Redis client URL`);
@ -81,6 +85,10 @@ fastify.ready(err => {
data = JSON.parse(data);
switch(data.message) {
case "fetch metadata":
fetchMetadata(data, socket);
break;
case "landed on homepage":
generateGitHubFeed(result => {
socket.send(JSON.stringify({
@ -92,8 +100,8 @@ fastify.ready(err => {
break;
case "fetch metadata":
fetchMetadata(data, socket);
case "subscribe":
newsletterSubscribe(data, socket);
break;
default:
@ -213,28 +221,41 @@ function fetchMetadata(data, socket) {
"type": "error"
}));
logSlackError("[daemon error]\n", "```" + JSON.stringify(uploadError) + "```");
logSlackError(
"\n" +
"> *DAEMON ERROR:* ```" + JSON.parse(JSON.stringify(uploadError)) + "```" + "\n" +
"> _Cause: Someone attempted to publish a meme via the Tour_\n"
);
return;
});
}
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => { // eslint-disable-line
request({
url: "http://daemon.lbry.tech",
qs: body
}, (error, response, body) => {
if (error) {
reject(error);
logSlackError("[daemon error]\n", "```" + JSON.stringify(error) + "```");
return;
logSlackError(
"\n" +
"> *DAEMON ERROR:* ```" + JSON.parse(JSON.stringify(error)) + "```" + "\n" +
"> _Cause: Someone is going through the Tour_\n"
);
return resolve(error);
}
body = JSON.parse(body);
if (typeof body.error !== "undefined") {
reject(body.error);
logSlackError("[daemon error]\n", "```" + JSON.stringify(body.error) + "```");
return;
logSlackError(
"\n" +
"> *DAEMON ERROR:* ```" + JSON.parse(JSON.stringify(body.error)) + "```" + "\n" +
"> _Cause: Someone is going through the Tour_\n"
);
return resolve(body.error);
}
socket.send(JSON.stringify({
@ -289,6 +310,73 @@ function generateGitHubFeed(displayGitHubFeed) {
}
}
function newsletterSubscribe(data, socket) {
const email = data.email;
if (!validateEmail(email)) return socket.send(JSON.stringify({
"html": "Your email is invalid",
"message": "updated html",
"selector": "#emailMessage"
}));
return new Promise((resolve, reject) => {
request({
method: "POST",
url: `https://api.lbry.io/list/subscribe?email=${email}`
}).then(body => {
if (!body || !JSON.parse(body)) {
logSlackError(
"\n" +
"> *NEWSLETTER ERROR:* ```¯\\_(ツ)_/¯ This should be an unreachable error```" + "\n" +
`> _Cause: ${email} interacted with the form_\n`
);
return resolve(socket.send(JSON.stringify({
"html": "Something is terribly wrong",
"message": "updated html",
"selector": "#emailMessage"
})));
}
body = JSON.parse(body);
if (!body.success) {
logSlackError(
"\n" +
"> *NEWSLETTER ERROR:* ```" + JSON.parse(JSON.stringify(body.error)) + "```" + "\n" +
`> _Cause: ${email} interacted with the form_\n`
);
return reject(socket.send(JSON.stringify({
"html": body.error,
"message": "updated html",
"selector": "#emailMessage"
})));
}
return resolve(socket.send(JSON.stringify({
"html": "Thank you! Please confirm subscription in your inbox.",
"message": "updated html",
"selector": "#emailMessage"
})));
}).catch(welp => {
if (welp.statusCode === 409) {
logSlackError(
"\n" +
"> *NEWSLETTER ERROR:* ```" + JSON.parse(JSON.stringify(welp.error)) + "```" + "\n" +
`> _Cause: ${email} interacted with the form_\n`
);
return resolve(socket.send(JSON.stringify({
"html": "You have already subscribed!",
"message": "updated html",
"selector": "#emailMessage"
})));
}
});
});
}
function uploadImage(imageSource) {
return new Promise((resolve, reject) => {
request({
@ -308,3 +396,8 @@ function uploadImage(imageSource) {
});
});
}
function validateEmail(email) {
const re = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\\.,;:\s@"]{2,})$/i;
return re.test(String(email));
}

View file

@ -11,14 +11,14 @@ const html = require("choo-async/html");
// E X P O R T
module.exports = exports = () => html`
<div id="email-subscribe" class="newsletter-cta">
<div id="emailSubscribe" class="newsletter-cta">
<h3 class="newsletter-cta__title">Don't miss a bit - Subscribe for LBRY technical updates</h3>
<div>
<input type="text" class="newsletter-cta__input" v-model="emailAddress" placeholder="you@domain.tld">
<a class="newsletter-cta__submit" href="#" v-on:click.prevent="subscribe" title="Subscribe to our technical newsletter">Subscribe</a>
<input class="newsletter-cta__input" id="emailAddress" placeholder="you@domain.tld" type="text"/>
<button class="newsletter-cta__submit" data-action="subscribe to newsletter" title="Subscribe to our technical newsletter" type="button">Subscribe</a>
</div>
<p class="newsletter-cta__message"></p>
<p class="newsletter-cta__message" id="emailMessage"></p>
</div>
`;

View file

@ -23,16 +23,11 @@ module.exports = exports = state => html`
<section class="alert" id="alert-beta">
<div class="inner-wrap">
<p>
<strong>This website is in beta and under heavy development.</strong>
All information should be considered incomplete and possibly incorrect and things may not work as expected.
</p>
<p><strong>This website is in beta and under heavy development.</strong>All information should be considered incomplete and possibly incorrect and things may not work as expected.</p>
<br/><br/>
<p>
Please do not share or link this site publicly while this message is here. This website is open source and you can <a href="https://github.com/lbryio/lbry.tech" target="_blank" rel="noopener noreferrer">contribute to it on Github</a>.
</p>
<p>Please do not share or link this site publicly while this message is here. This website is open source and you can <a href="https://github.com/lbryio/lbry.tech" target="_blank" rel="noopener noreferrer">contribute to it on Github</a>.</p>
<button id="close-alert">&times;</button>
</div>