Bug 1408334 - add form to subscribe to mozilla developer newsletter in about:devtools draft
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 31 Oct 2017 10:19:00 +0100
changeset 692154 b6130b8dbcab0bc1845f74cdadd44833f3ec0ae6
parent 692153 4ca45dde569abab576eb46abe1f7496866140402
child 738681 490fbbc48d8260cd6e2592ab165a9f3c8bf1a195
push id87416
push userjdescottes@mozilla.com
push dateThu, 02 Nov 2017 16:44:55 +0000
bugs1408334
milestone58.0a1
Bug 1408334 - add form to subscribe to mozilla developer newsletter in about:devtools MozReview-Commit-ID: JuJqNS3r6NH
devtools/shim/aboutdevtools/aboutdevtools.css
devtools/shim/aboutdevtools/aboutdevtools.xhtml
devtools/shim/aboutdevtools/subscribe.css
devtools/shim/aboutdevtools/subscribe.js
devtools/shim/jar.mn
--- a/devtools/shim/aboutdevtools/aboutdevtools.css
+++ b/devtools/shim/aboutdevtools/aboutdevtools.css
@@ -1,55 +1,63 @@
-:root {
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ :root {
   /* Photon color variables used on the aboutdevtools page */
   --blue-60: #0060df;
   --blue-70: #003eaa;
   --blue-80: #002275;
   --grey-30: #d7d7db;
+  --grey-90-alpha-30: rgba(12, 12, 13, .3);
+  --grey-90-alpha-40: rgba(12, 12, 13, .4);
+  --grey-90-alpha-50: rgba(12, 12, 13, .5);
+  --red-50: #ff0039;
+  --teal-60: #00c8d7;
   --white: #ffffff;
+
+  /* Shared variables */
+  --line-height: 1.5em;
 }
 
 html, body {
   min-width: 600px;
   height: 100%;
 }
 
 p {
-  line-height: 1.5em;
+  line-height: var(--line-height);
 }
 
 .box {
   width: 100%;
   max-width: 850px;
   display: flex;
-  align-items: center;
-  height: 400px;
   flex-shrink: 0;
+  padding: 34px 0 50px 0;
 }
 
 .wrapper {
   width: 100%;
   height: 100%;
   display: flex;
   flex-direction: column;
   align-items: center;
 }
 
 .left-pane {
-  width: 360px;
-  height: 100%;
+  width: 300px;
+  height: 300px;
   background-image: url(images/otter.svg);
-  background-size: 80%;
+  background-size: 100%;
   background-position: 50%;
   background-repeat: no-repeat;
   flex-shrink: 0;
-}
-
-.right-pane {
-  height: 250px;
+  margin-right: 20px;
 }
 
 .features {
   max-width: 980px;
   border-top: 1px solid var(--grey-30);
 }
 
 .features-list {
@@ -75,17 +83,20 @@ p {
   font-weight: 300;
   margin: 10px 0;
 }
 
 .feature-desc {
   margin: 1em 20px;
 }
 
-.installpage-link {
+.external,
+.external:hover,
+.external:visited,
+.external:hover:active {
   color: var(--blue-60);
   -moz-context-properties: fill;
   fill: var(--blue-60);
 }
 
 .external::after {
   content: "";
 
@@ -103,47 +114,47 @@ p {
 
 .title {
   font-weight: 300;
   font-size: 32px;
   margin-top: 16px;
   line-height: 44px;
 }
 
-.installpage-button {
+.main-button {
   display: block;
 
-  margin: 2em 0 0 0;
+  margin: 20px 0 0 0;
   padding: 10px 20px;
 
   border: none;
   border-radius: 2px;
 
   font-size: 15px;
   font-weight: 400;
   line-height: 21px;
 
   background-color: var(--blue-60);
   color: var(--white);
   box-shadow: 0 1px 0 rgba(0,0,0,0.23);
   cursor: pointer;
 }
 
-.installpage-button:enabled:hover {
+.main-button:enabled:hover {
   background-color: var(--blue-70)
 }
 
-.installpage-button:active,
-.installpage-button:hover:active,
-.installpage-button:enabled:hover:active {
+.main-button:active,
+.main-button:hover:active,
+.main-button:enabled:hover:active {
   background-color: var(--blue-80);
 }
 
 /* Remove light gray outline when clicking on the button */
-.installpage-button::-moz-focus-inner {
+.main-button::-moz-focus-inner {
   border: 0;
 }
 
 [hidden="true"] {
   display: none;
 }
 
 footer {
--- a/devtools/shim/aboutdevtools/aboutdevtools.xhtml
+++ b/devtools/shim/aboutdevtools/aboutdevtools.xhtml
@@ -9,17 +9,19 @@
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml" dir="&locale.dir;">
 <head>
   <title>&aboutDevtools.headTitle;</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>a
   <link rel="stylesheet" href="chrome://global/skin/in-content/common.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools-shim/content/aboutdevtools/aboutdevtools.css"  type="text/css"/>
+  <link rel="stylesheet" href="chrome://devtools-shim/content/aboutdevtools/subscribe.css"  type="text/css"/>
   <script type="application/javascript" src="chrome://devtools-shim/content/aboutdevtools/aboutdevtools.js"></script>
+  <script type="application/javascript" src="chrome://devtools-shim/content/aboutdevtools/subscribe.js"></script>
 </head>
 <body>
   <div id="install-page" class="wrapper" hidden="true">
     <div class="box">
       <div class="left-pane" />
       <div class="right-pane">
         <h1 class="title" id="common-title" hidden="true">&aboutDevtools.enable.title;</h1>
         <h1 class="title" id="inspect-title" hidden="true">&aboutDevtools.enable.inspectElementTitle;</h1>
@@ -28,28 +30,57 @@
              as we can't lazily load localized strings from dtd -->
         <p id="about-debugging-message" hidden="true">&aboutDevtools.enable.aboutDebuggingMessage;</p>
         <p id="menu-message" hidden="true">&aboutDevtools.enable.menuMessage;</p>
         <p id="key-shortcut-message" hidden="true">&aboutDevtools.enable.keyShortcutMessage;</p>
         <p id="inspect-element-message" hidden="true">&aboutDevtools.enable.inspectElementMessage;</p>
 
         <p>&aboutDevtools.enable.commonMessage;</p>
         <a class="external installpage-link" href="https://developer.mozilla.org/docs/Tools" target="_blank">&aboutDevtools.enable.learnMoreLink;</a>
-        <button class="installpage-button" id="install">&aboutDevtools.enable.installButton;</button>
+        <button class="main-button" id="install">&aboutDevtools.enable.installButton;</button>
       </div>
     </div>
   </div>
 
   <!-- This page, hidden by default is displayed once the add-on is installed -->
   <div id="welcome-page" class="wrapper" hidden="true">
     <div class="box">
       <div class="left-pane" />
       <div class="right-pane">
         <h1 class="title" >&aboutDevtools.welcome.title;</h1>
         <p id="welcome-message">&aboutDevtools.welcome.message;</p>
+
+        <!-- Form dedicated to the newsletter subscription -->
+        <div class="newsletter">
+          <h2 class="newsletter-title">Mozilla Developer Newsletter</h2>
+          <p>Get developer news, tricks and resources sent straight to your inbox.</p>
+
+          <form id="newsletter-form" name="newsletter-form" action="https://www.mozilla.org/en-US/newsletter/" method="post">
+            <input type="hidden" id="fmt" name="fmt" value="H" />
+            <input type="hidden" id="newsletters" name="newsletters" value="app-dev" />
+            <div id="newsletter_errors"></div>
+            <div id="newsletter_email" class="newsletter-form-section">
+              <input type="email" id="email" name="email" class="form_input" required="true" placeholder="Email" />
+            </div>
+
+            <div id="newsletter-privacy" class="newsletter-form-section">
+              <input type="checkbox" id="privacy" name="privacy" required="true" />
+              <label for="privacy">
+              I'm okay with Mozilla handling my info as explained in this <a class="external" href="https://www.mozilla.org/privacy/">Privacy Policy</a>.
+              </label>
+            </div>
+            <div>
+              <button type="submit" class="main-button">Subscribe</button>
+            </div>
+          </form>
+          <div id="newsletter-thanks">
+            <h2>Thanks!</h2>
+            <p>If you haven’t previously confirmed a subscription to a Mozilla-related newsletter you may have to do so. Please check your inbox or your spam filter for an email from us.</p>
+          </div>
+        </div>
       </div>
     </div>
 
     <div class="features">
       <ul class="features-list">
         <li class="feature">
           <img class="feature-icon" src="chrome://devtools-shim/content/aboutdevtools/images/feature-inspector.svg" alt=""/>
           <h3 class="feature-name">Inspector</h3>
new file mode 100644
--- /dev/null
+++ b/devtools/shim/aboutdevtools/subscribe.css
@@ -0,0 +1,93 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#newsletter_errors {
+  display: none; /* hide by default */
+  margin-bottom: 20px;
+  border-radius: 2px;
+  padding: 10px;
+  background-color: var(--red-50);
+  color: var(--white);
+}
+
+#newsletter_errors .error:last-child {
+  margin: 0 0 10px 0;
+}
+
+#newsletter_errors .error:last-child {
+  margin-bottom: 0;
+}
+
+#newsletter-thanks {
+  display: none;
+}
+
+.newsletter-form-section {
+  display: block;
+  margin-bottom: 20px;
+  width: 320px;
+}
+
+#newsletter-privacy {
+  display: flex;
+
+  /* The privacy section is hidden by default and only displayed on focus */
+  transition: all 0.5s;
+  height: 0;
+  margin-bottom: -20px;
+  overflow: hidden;
+}
+
+#newsletter-privacy.show {
+  height: 65px;
+}
+
+#newsletter-privacy label {
+  line-height: var(--line-height);
+}
+
+#privacy {
+  width: 20px;
+  height: 20px;
+  margin: 2px;
+  margin-inline-end: 10px;
+  flex-shrink: 0;
+  border-color: var(--grey-90-alpha-30);
+}
+
+#email {
+  width: 100%;
+  box-sizing: border-box;
+  padding: 12px 15px;
+  border-color: var(--grey-90-alpha-30);
+}
+
+#email:hover,
+#privacy:hover{
+  border-color: var(--grey-90-alpha-50);
+}
+
+#email:focus,
+#privacy:focus {
+  border-color: var(--teal-60);
+  box-shadow: 0 0 2px 0 var(--teal-60);
+}
+
+#newsletter-form button {
+  cursor: pointer;
+}
+
+#newsletter-form button::-moz-focus-inner,
+#newsletter-form input[type="button"]::-moz-focus-inner,
+#newsletter-form input[type="submit"]::-moz-focus-inner,
+#newsletter-form input[type="reset"]::-moz-focus-inner {
+  padding: 0 !important;
+  border: 0 none !important;
+  cursor: pointer;
+}
+
+#newsletter-form ::placeholder {
+  color: var(--grey-90-alpha-40);
+}
+
new file mode 100644
--- /dev/null
+++ b/devtools/shim/aboutdevtools/subscribe.js
@@ -0,0 +1,115 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+window.addEventListener("load", function () {
+  let newsletterForm = document.getElementById("newsletter-form");
+  let emailInput = document.getElementById("email");
+
+  // Show the additional form fields on focus of the email input.
+  emailInput.addEventListener("focus", () => {
+    document.getElementById("newsletter_privacy").classList.add("show");
+  });
+
+  // Handle errors.
+  let errorArray = [];
+  let newsletterErrors = document.getElementById("newsletter_errors");
+  function newsletterError(e) {
+    if (errorArray.length) {
+      for (let i = 0; i < errorArray.length; i++) {
+        let item = document.createElement("p");
+        item.classList.add("error");
+        item.appendChild(document.createTextNode(errorArray[i]));
+        newsletterErrors.appendChild(item);
+      }
+    } else {
+      // No error messages, forward to server for better troubleshooting.
+      newsletterForm.setAttribute("data-skip-xhr", true);
+      newsletterForm.submit();
+    }
+
+    newsletterErrors.style.display = "block";
+  }
+
+  // Show sucess message.
+  function newsletterThanks() {
+    let thanks = document.getElementById("newsletter-thanks");
+    thanks.style.display = "block";
+  }
+
+  // XHR subscribe; handle errors; display thanks message on success.
+  function newsletterSubscribe(evt) {
+    let skipXHR = newsletterForm.getAttribute("data-skip-xhr");
+    if (skipXHR) {
+      return true;
+    }
+    evt.preventDefault();
+    evt.stopPropagation();
+
+    // New submission, clear old errors
+    errorArray = [];
+    newsletterErrors.style.display = "none";
+    while (newsletterErrors.firstChild) {
+      newsletterErrors.firstChild.remove();
+    }
+
+    let fmt = document.getElementById("fmt").value;
+    let email = document.getElementById("email").value;
+    let newsletter = document.getElementById("newsletters").value;
+
+    let isPrivacyChecked = document.querySelector('input[name="privacy"]:checked');
+    let privacy = isPrivacyChecked ? "&privacy=true" : "";
+    let params = "email=" + encodeURIComponent(email) +
+                  "&newsletters=" + newsletter +
+                  privacy +
+                  "&fmt=" + fmt;
+
+    let xhr = new XMLHttpRequest();
+
+    xhr.onload = function (r) {
+      if (r.target.status >= 200 && r.target.status < 300) {
+        let response = r.target.response;
+
+        // response is null if handled by service worker
+        if (response === null) {
+          newsletterError(new Error());
+          return;
+        }
+
+        if (response.success === true) {
+          newsletterForm.style.display = "none";
+          newsletterThanks();
+        } else {
+          if (response.errors) {
+            for (let i = 0; i < response.errors.length; i++) {
+              errorArray.push(response.errors[i]);
+            }
+          }
+          newsletterError(new Error());
+        }
+      } else {
+        newsletterError(new Error());
+      }
+    };
+
+    xhr.onerror = function (e) {
+      newsletterError(e);
+    };
+
+    let url = newsletterForm.getAttribute("action");
+
+    xhr.open("POST", url, true);
+    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+    xhr.timeout = 5000;
+    xhr.ontimeout = newsletterError;
+    xhr.responseType = "json";
+    xhr.send(params);
+
+    return false;
+  }
+
+  newsletterForm.addEventListener("submit", newsletterSubscribe);
+}, { once: true });
--- a/devtools/shim/jar.mn
+++ b/devtools/shim/jar.mn
@@ -2,16 +2,18 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 devtools-shim.jar:
 %   content devtools-shim %content/
     content/aboutdevtools/aboutdevtools.xhtml  (aboutdevtools/aboutdevtools.xhtml)
     content/aboutdevtools/aboutdevtools.css (aboutdevtools/aboutdevtools.css)
     content/aboutdevtools/aboutdevtools.js (aboutdevtools/aboutdevtools.js)
+    content/aboutdevtools/subscribe.css (aboutdevtools/subscribe.css)
+    content/aboutdevtools/subscribe.js (aboutdevtools/subscribe.js)
 
     content/aboutdevtools/images/otter.svg (aboutdevtools/images/otter.svg)
 
     # Temporary localisation file, move back to devtools/shim/locales/en-US when ready for localization
     # See https://bugzilla.mozilla.org/show_bug.cgi?id=1408369
     content/aboutdevtools/tmp-locale/aboutdevtools.dtd (aboutdevtools/tmp-locale/aboutdevtools.dtd)
 
     content/aboutdevtools/images/dev-edition-logo.svg (aboutdevtools/images/dev-edition-logo.svg)