From 253e3be3093d18f93611a027499cbbcc2bcfe8cf Mon Sep 17 00:00:00 2001 From: benjamin hoffman <6520022+benjaminhoffman@users.noreply.github.com> Date: Sun, 24 Dec 2017 15:18:47 -0800 Subject: [PATCH 1/6] Adds email capture to bottom of blog --- www/src/components/email-capture-form.js | 77 ++++++++++++++++++++++++ www/src/templates/template-blog-post.js | 2 + 2 files changed, 79 insertions(+) create mode 100644 www/src/components/email-capture-form.js diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js new file mode 100644 index 0000000000000..25e8b0a5b280a --- /dev/null +++ b/www/src/components/email-capture-form.js @@ -0,0 +1,77 @@ +import React from "react" +import { rhythm } from "../utils/typography" +import presets from "../utils/presets" + +class EmailCaptureForm extends React.Component { + constructor() { + super() + this.state = { + email: ``, + } + } + + render() { + return ( +
+ Enjoyed this post? Receive the next in your inbox! +
+
{ + e.preventDefault() + e.stopPropagation() + this.setState({ + email: e.target[`email`].value, + pathname: window.location.pathname, + }) + }} + > + {this.state.email ? ( +
+ Thank you! Youʼll receive your first email shortly. +
+ ) : ( +
+ + +
+ )} +
+
+ ) + } +} + +export default EmailCaptureForm diff --git a/www/src/templates/template-blog-post.js b/www/src/templates/template-blog-post.js index ffebb0cbae324..1579432fe96f4 100644 --- a/www/src/templates/template-blog-post.js +++ b/www/src/templates/template-blog-post.js @@ -8,6 +8,7 @@ import Img from "gatsby-image" import presets from "../utils/presets" import typography, { rhythm, scale, options } from "../utils/typography" import Container from "../components/container" +import EmailCaptureForm from '../components/email-capture-form' class BlogPostTemplate extends React.Component { render() { @@ -200,6 +201,7 @@ class BlogPostTemplate extends React.Component { __html: this.props.data.markdownRemark.html, }} /> +
Date: Sun, 24 Dec 2017 15:18:47 -0800 Subject: [PATCH 2/6] Adds email capture to bottom of blog --- www/src/components/email-capture-form.js | 77 ++++++++++++++++++++++++ www/src/templates/template-blog-post.js | 2 + 2 files changed, 79 insertions(+) create mode 100644 www/src/components/email-capture-form.js diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js new file mode 100644 index 0000000000000..25e8b0a5b280a --- /dev/null +++ b/www/src/components/email-capture-form.js @@ -0,0 +1,77 @@ +import React from "react" +import { rhythm } from "../utils/typography" +import presets from "../utils/presets" + +class EmailCaptureForm extends React.Component { + constructor() { + super() + this.state = { + email: ``, + } + } + + render() { + return ( +
+ Enjoyed this post? Receive the next in your inbox! +
+
{ + e.preventDefault() + e.stopPropagation() + this.setState({ + email: e.target[`email`].value, + pathname: window.location.pathname, + }) + }} + > + {this.state.email ? ( +
+ Thank you! Youʼll receive your first email shortly. +
+ ) : ( +
+ + +
+ )} +
+
+ ) + } +} + +export default EmailCaptureForm diff --git a/www/src/templates/template-blog-post.js b/www/src/templates/template-blog-post.js index ffebb0cbae324..1579432fe96f4 100644 --- a/www/src/templates/template-blog-post.js +++ b/www/src/templates/template-blog-post.js @@ -8,6 +8,7 @@ import Img from "gatsby-image" import presets from "../utils/presets" import typography, { rhythm, scale, options } from "../utils/typography" import Container from "../components/container" +import EmailCaptureForm from '../components/email-capture-form' class BlogPostTemplate extends React.Component { render() { @@ -200,6 +201,7 @@ class BlogPostTemplate extends React.Component { __html: this.props.data.markdownRemark.html, }} /> +
Date: Thu, 28 Dec 2017 11:52:59 -0800 Subject: [PATCH 3/6] Adds Mailchimp functionality --- www/package.json | 1 + www/src/components/email-capture-form.js | 176 ++++++++++++++++------- 2 files changed, 123 insertions(+), 54 deletions(-) diff --git a/www/package.json b/www/package.json index 106f4eee86da8..dbe46803004e3 100644 --- a/www/package.json +++ b/www/package.json @@ -38,6 +38,7 @@ "gatsby-transformer-yaml": "^1.5.7", "graphql-request": "^1.4.0", "gray-percentage": "^2.0.0", + "jsonp": "^0.2.1", "limax": "^1.5.0", "lodash": "^4.16.6", "mitt": "^1.1.2", diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js index 25e8b0a5b280a..f54c33bc352c6 100644 --- a/www/src/components/email-capture-form.js +++ b/www/src/components/email-capture-form.js @@ -1,13 +1,84 @@ import React from "react" import { rhythm } from "../utils/typography" import presets from "../utils/presets" +import jsonp from "jsonp" + +// Mailchimp endpoint +// From: https://us17.admin.mailchimp.com/lists/integration/embeddedcode?id=XXXXXX +// Where `XXXXXX` is the MC list ID +// Note: we change `/post` to `/post-json` +const MAILCHIMP_URL = `https://gatsbyjs.us17.list-manage.com/subscribe/post-json?u=1dc33f19eb115f7ebe4afe5ee&id=f366064ba7` class EmailCaptureForm extends React.Component { - constructor() { - super() - this.state = { - email: ``, + state = { + email: ``, + } + + // Update state each time user edits their email address + _handleEmailChange = e => { + this.setState({ email: e.target.value }) + } + + // Check whether the email address is valid + // 1) not an empty string + // 2) greater than 5 characters + // 3) includes both a `@` and `.` + _isValidEmailAddress = email => + !!email && email.length > 5 && (email.includes(`@`) && email.includes(`.`)) + + _handleFormSubmit = e => { + e.preventDefault() + e.stopPropagation() + + // If email is not valid, break early + if (!this._isValidEmailAddress(this.state.email)) { + this.setState({ + status: `error`, + msg: `${this.state.email} is not a valid email address`, + }) + return } + + // Construct the url for our jsonp request + // Query params must be in CAPS + const url = `${MAILCHIMP_URL} + &EMAIL=${encodeURIComponent(this.state.email)} + &PATHNAME=${window.location.pathname} + ` + + this.setState( + { + msg: null, + status: `sending`, + }, + // setState callback (jsonp) + () => + jsonp( + url, + { + param: `c`, + }, + // jsonp callback + (err, data) => { + if (err) { + this.setState({ + status: `error`, + msg: err, + }) + } else if (data.result !== `success`) { + this.setState({ + status: `error`, + msg: data.msg, + }) + } else { + this.setState({ + status: `success`, + msg: data.msg, + }) + } + } + ) + ) } render() { @@ -17,58 +88,55 @@ class EmailCaptureForm extends React.Component { border: `2px solid ${presets.brand}`, backgroundColor: presets.veryLightPurple, borderRadius: `4px`, - padding: `${rhythm(0.75)} 0 0 ${rhythm(0.75)}`, + padding: `${rhythm(0.75)}`, }} - > - Enjoyed this post? Receive the next in your inbox! -
-
{ - e.preventDefault() - e.stopPropagation() - this.setState({ - email: e.target[`email`].value, - pathname: window.location.pathname, - }) - }} > - {this.state.email ? ( -
- Thank you! Youʼll receive your first email shortly. -
- ) : ( -
- - -
- )} -
+ {this.state.status === `success` ? ( +
Thank you! Youʼll receive your first email shortly.
+ ) : ( +
+ Enjoyed this post? Receive the next one in your inbox! +
+
+
+ + + {this.state.status === `error` && ( +
+ )} +
+ +
+ )}
) } From 3066ff513a7039005e220aca4f2e14af27a56430 Mon Sep 17 00:00:00 2001 From: benjamin hoffman <6520022+benjaminhoffman@users.noreply.github.com> Date: Sat, 30 Dec 2017 17:00:13 -0800 Subject: [PATCH 4/6] Refactors postEmailToMailchimp method, updates cc --- www/src/components/email-capture-form.js | 155 +++++++++++++---------- 1 file changed, 85 insertions(+), 70 deletions(-) diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js index 842a533888605..085afa6a49eb0 100644 --- a/www/src/components/email-capture-form.js +++ b/www/src/components/email-capture-form.js @@ -10,8 +10,11 @@ import jsonp from "jsonp" const MAILCHIMP_URL = `https://gatsbyjs.us17.list-manage.com/subscribe/post-json?u=1dc33f19eb115f7ebe4afe5ee&id=f366064ba7` class EmailCaptureForm extends React.Component { - state = { - email: ``, + constructor() { + super() + this.state = { + email: ``, + } } // Update state each time user edits their email address @@ -20,12 +23,42 @@ class EmailCaptureForm extends React.Component { } // Check whether the email address is valid: - // not an empty string, - // greater than 5 characters, - // includes both `@` and `.` + // - not an empty string, + // - greater than 5 characters, + // - includes both `@` and `.` _isValidEmailAddress = email => !!email && email.length > 5 && (email.includes(`@`) && email.includes(`.`)) + // Using jsonp, post to MC server & handle its response + _postEmailToMailchimp = url => { + // jsonp lib takes an `endpoint`, {options}, & callback + jsonp(url, { param: `c` }, (err, data) => { + // network failures, timeouts, etc + if (err) { + this.setState({ + status: `error`, + msg: err, + }) + + // Mailchimp errors & failures + } else if (data.result !== `success`) { + this.setState({ + status: `error`, + msg: data.msg, + }) + + // Posted email successfully to Mailchimp + } else { + this.setState({ + status: `success`, + msg: data.msg, + }) + } + }) + } + + // On form submit, validate email + // then jsonp to Mailchimp, and update state _handleFormSubmit = e => { e.preventDefault() e.stopPropagation() @@ -34,13 +67,14 @@ class EmailCaptureForm extends React.Component { if (!this._isValidEmailAddress(this.state.email)) { this.setState({ status: `error`, - msg: `${this.state.email} is not a valid email address`, + msg: `"${this.state.email}" is not a valid email address`, }) return } // Construct the url for our jsonp request // Query params must be in CAPS + // Capture pathname for better email targeting const url = `${MAILCHIMP_URL} &EMAIL=${encodeURIComponent(this.state.email)} &PATHNAME=${window.location.pathname} @@ -51,33 +85,8 @@ class EmailCaptureForm extends React.Component { msg: null, status: `sending`, }, - // setState callback (jsonp) - () => - jsonp( - url, - { - param: `c`, - }, - // jsonp callback - (err, data) => { - if (err) { - this.setState({ - status: `error`, - msg: err, - }) - } else if (data.result !== `success`) { - this.setState({ - status: `error`, - msg: data.msg, - }) - } else { - this.setState({ - status: `success`, - msg: data.msg, - }) - } - } - ) + // jsonp request as setState callback + this._postEmailToMailchimp(url) ) } @@ -90,50 +99,56 @@ class EmailCaptureForm extends React.Component { borderRadius: `4px`, padding: `${rhythm(0.75)}`, }} - > + > {this.state.status === `success` ? (
Thank you! Youʼll receive your first email shortly.
) : (
Enjoyed this post? Receive the next one in your inbox!
-
-
- +
+ + + {this.state.status === `error` && ( +
- - {this.state.status === `error` && ( -
- )} -
+ )} +
)} From 0d6f9f91d6e0946790fdb9a0b67b334353b90b9e Mon Sep 17 00:00:00 2001 From: benjamin hoffman <6520022+benjaminhoffman@users.noreply.github.com> Date: Wed, 3 Jan 2018 20:36:56 -0800 Subject: [PATCH 5/6] updates rhythm css, installs & uses validator module --- www/package.json | 3 ++- www/src/components/email-capture-form.js | 32 ++++++++++-------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/www/package.json b/www/package.json index dbe46803004e3..4b3cee1d28ad6 100644 --- a/www/package.json +++ b/www/package.json @@ -48,7 +48,8 @@ "typeface-space-mono": "^0.0.40", "typeface-spectral": "^0.0.40", "typography-breakpoint-constants": "^0.15.10", - "typography-plugin-code": "^0.16.11" + "typography-plugin-code": "^0.16.11", + "validator": "^9.2.0" }, "keywords": [ "gatsby" diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js index 085afa6a49eb0..89634ccaef5b6 100644 --- a/www/src/components/email-capture-form.js +++ b/www/src/components/email-capture-form.js @@ -2,6 +2,7 @@ import React from "react" import { rhythm } from "../utils/typography" import presets from "../utils/presets" import jsonp from "jsonp" +import { validate } from "email-validator" // Mailchimp endpoint // From: https://us17.admin.mailchimp.com/lists/integration/embeddedcode?id=XXXXXX @@ -22,13 +23,6 @@ class EmailCaptureForm extends React.Component { this.setState({ email: e.target.value }) } - // Check whether the email address is valid: - // - not an empty string, - // - greater than 5 characters, - // - includes both `@` and `.` - _isValidEmailAddress = email => - !!email && email.length > 5 && (email.includes(`@`) && email.includes(`.`)) - // Using jsonp, post to MC server & handle its response _postEmailToMailchimp = url => { // jsonp lib takes an `endpoint`, {options}, & callback @@ -40,14 +34,14 @@ class EmailCaptureForm extends React.Component { msg: err, }) - // Mailchimp errors & failures + // Mailchimp errors & failures } else if (data.result !== `success`) { this.setState({ status: `error`, msg: data.msg, }) - // Posted email successfully to Mailchimp + // Posted email successfully to Mailchimp } else { this.setState({ status: `success`, @@ -64,7 +58,7 @@ class EmailCaptureForm extends React.Component { e.stopPropagation() // If email is not valid, break early - if (!this._isValidEmailAddress(this.state.email)) { + if (!validate(this.state.email)) { this.setState({ status: `error`, msg: `"${this.state.email}" is not a valid email address`, @@ -97,7 +91,7 @@ class EmailCaptureForm extends React.Component { border: `2px solid ${presets.brand}`, backgroundColor: presets.veryLightPurple, borderRadius: `4px`, - padding: `${rhythm(0.75)}`, + padding: `${rhythm(1 / 2)}`, }} > {this.state.status === `success` ? ( @@ -119,10 +113,10 @@ class EmailCaptureForm extends React.Component { placeholder="you@email.com" onChange={this._handleEmailChange} css={{ - marginTop: rhythm(0.3), - padding: `${rhythm(0.3)} ${rhythm(0.3)} ${rhythm( - 0.3 - )} ${rhythm(0.7)}`, + marginTop: rhythm(1 / 4), + padding: `${rhythm(1 / 4)} ${rhythm(1 / 4)} ${rhythm( + 1 / 4 + )} ${rhythm(1 / 2)}`, width: `250px`, color: presets.bodyColor, }} @@ -132,12 +126,12 @@ class EmailCaptureForm extends React.Component { onClick={this._handleFormSubmit} css={{ borderRadius: `2px`, - border: `2px solid ${presets.brand}`, + border: `${rhythm(1 / 4)} solid ${presets.brand}`, backgroundColor: presets.brand, height: `43px`, cursor: `pointer`, - padding: `0 ${rhythm(0.75)} 0 ${rhythm(0.75)}`, - margin: `${rhythm(0.75)} 0 0 ${rhythm(0.75)}`, + padding: `0 ${rhythm(1 / 2)} 0 ${rhythm(1 / 2)}`, + margin: `${rhythm(1 / 2)} 0 0 ${rhythm(1 / 2)}`, }} > Subscribe @@ -145,7 +139,7 @@ class EmailCaptureForm extends React.Component { {this.state.status === `error` && (
)}
From 00b2fd8b9d7169c3c7728bea40e0e59be9aaaaf8 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 15 Jan 2018 08:55:39 -0800 Subject: [PATCH 6/6] Fiddle with design --- www/package.json | 1 + www/src/components/email-capture-form.js | 34 ++++++++++++++---------- www/src/templates/template-blog-post.js | 2 +- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/www/package.json b/www/package.json index 4b3cee1d28ad6..d3eb9323227b2 100644 --- a/www/package.json +++ b/www/package.json @@ -5,6 +5,7 @@ "author": "Kyle Mathews ", "dependencies": { "bluebird": "^3.5.1", + "email-validator": "^1.1.1", "gatsby": "^1.9.77", "gatsby-image": "^1.0.14", "gatsby-link": "^1.6.23", diff --git a/www/src/components/email-capture-form.js b/www/src/components/email-capture-form.js index 89634ccaef5b6..6a80a6c634386 100644 --- a/www/src/components/email-capture-form.js +++ b/www/src/components/email-capture-form.js @@ -3,6 +3,12 @@ import { rhythm } from "../utils/typography" import presets from "../utils/presets" import jsonp from "jsonp" import { validate } from "email-validator" +import { css } from "glamor" + +let stripeAnimation = css.keyframes({ + "0%": { backgroundPosition: `0 0` }, + "100%": { backgroundPosition: `30px 60px` }, +}) // Mailchimp endpoint // From: https://us17.admin.mailchimp.com/lists/integration/embeddedcode?id=XXXXXX @@ -88,18 +94,16 @@ class EmailCaptureForm extends React.Component { return (
{this.state.status === `success` ? (
Thank you! Youʼll receive your first email shortly.
) : (
- Enjoyed this post? Receive the next one in your inbox! -
+

Enjoyed this post? Receive the next one in your inbox!

Subscribe diff --git a/www/src/templates/template-blog-post.js b/www/src/templates/template-blog-post.js index 1579432fe96f4..740f2802963ff 100644 --- a/www/src/templates/template-blog-post.js +++ b/www/src/templates/template-blog-post.js @@ -8,7 +8,7 @@ import Img from "gatsby-image" import presets from "../utils/presets" import typography, { rhythm, scale, options } from "../utils/typography" import Container from "../components/container" -import EmailCaptureForm from '../components/email-capture-form' +import EmailCaptureForm from "../components/email-capture-form" class BlogPostTemplate extends React.Component { render() {