This commit is contained in:
lesleyjanenorton 2019-03-28 11:14:45 -05:00
Родитель e4762560dc
Коммит 1adc809c45
28 изменённых файлов: 454 добавлений и 272 удалений

Просмотреть файл

@ -476,7 +476,7 @@ fxa-account= {-brand-fxa}
open-fxa-menu=Open {-brand-fxa} navigation
latest-breach= Latest breach added to {-product-name}
breach-added= Added
breach-added= Added:
more-about-this-breach= More about this breach
how-hackers-work= Understand How Hackers Work
@ -494,3 +494,12 @@ search-all-emails= Search all your email addresses for breaches and get alerts a
keep-your-data-safe= Find out what you need to do to keep your data safe from cyber criminals.
monitor-several-emails= Monitor several emails
get-expert-advice= Get ongoing expert advice
email-addresses= Email Addresses
being-monitored= being monitored
data-breaches= Data Breaches
exposed-your-info= have exposed your information
passwords-exposed= Passwords Exposed
across-all-breaches= across all breaches

Просмотреть файл

@ -18,6 +18,8 @@ body {
--subhead: 1.1rem;
--lineHeight: 180%;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
background-color: rgba(249, 249, 250, 1);
@ -27,7 +29,6 @@ body {
overflow-y: scroll;
overflow-x: hidden;
min-height: 100vh;
height: 100%;
width: 100vw;
-webkit-overflow-scrolling: touch;
}
@ -36,10 +37,14 @@ p {
line-height: var(--lineHeight);
}
.bold {
font-weight: 600;
}
h1,
h2,
h3 {
margin-top: 0px;
margin-top: 0;
}
.big-headline {
@ -88,7 +93,7 @@ button:focus,
div:focus,
input:focus {
border: 1px solid rgb(40, 97, 205);
box-shadow: 0 0 0 1px rgb(63, 97, 217), 0 0 0 4px rgba(63, 97, 217, .3);
box-shadow: 0 0 0 1px rgb(63, 97, 217), 0 0 0 4px rgba(63, 97, 217, 0.3);
outline: none;
}
@ -100,6 +105,16 @@ button {
cursor: pointer;
justify-content: center;
text-align: center;
border-radius: 3px;
}
.utility-button {
border: 1px solid var(--color);
padding: 2rem 0;
width: 100%;
margin: auto;
max-width: 300px;
background-color: rgba(255, 255, 255, 0);
}
ul {
@ -120,6 +135,7 @@ ul li {
}
.row {
justify-content: space-between;
padding: 0.75rem;
}
@ -143,7 +159,6 @@ ul li {
width: 100%;
}
.container,
.content-box,
.row,
@ -183,6 +198,7 @@ ul li {
.col-8 {
flex: 1 1 66.66666667%;
min-width: 66.66666667%;
max-width: 66.66666667%;
}
@ -212,6 +228,11 @@ ul li {
text-align: center;
}
.al-cntr {
align-items: center;
align-content: center;
}
.bg-white {
background-color: white;
}
@ -229,10 +250,40 @@ div.sprite {
.logo-wrapper {
width: 1.5rem;
min-height: 10px;
margin-right: .5rem;
margin-right: 0.5rem;
display: inline-flex;
}
.brdr {
border: 1px solid #eee;
border-radius: 3px;
}
.pad-0 {
padding: 0;
}
.show {
visibility: visible;
opacity: 1;
transition: opacity 0.1s ease, visibility 0.1s ease 0.2s, max-height 0.1s ease 0.2s, padding 0.1s ease 0.2s;
}
.hide {
padding: 0;
opacity: 0;
max-height: 0;
visibility: hidden;
transition: opacity 0.1s ease, visibility 0.1s ease 0.2s, max-height 0.1s ease 0.2s, padding 0.1s ease 0.2s;
}
.hide > * {
padding: 0;
max-height: 0;
visibility: hidden;
margin: 0 auto !important;
}
@media screen and (max-width: 1000px) {
body {
--maxWidth: 800px;

Просмотреть файл

@ -14,14 +14,7 @@
display: inline-flex;
justify-content: flex-start;
margin-left: 1.5rem;
margin-bottom: 0px;
}
.article-list .logo-wrapper {
background-color: rgba(36, 34, 45, 0);
border: 1px solid rgba(36, 34, 45, .2);
border-radius: 50%;
transition: all 0.2s ease;
margin-bottom: 0;
}
.article-list a {
@ -30,11 +23,15 @@
}
.article-list .logo-wrapper {
background-color: rgba(36, 34, 45, 0);
border: 1px solid rgba(36, 34, 45, 0.2);
border-radius: 50%;
height: 1rem;
width: 1rem;
transition: all 0.2s ease;
}
.article-list .logo-title-wrapper:hover .logo-wrapper {
background-color: rgba(36, 34, 45, .1);
background-color: rgba(36, 34, 45, 0.1);
transition: all 0.2s ease;
}

Просмотреть файл

@ -1,27 +1,6 @@
.breach-listing {
border: 1px solid #eee;
overflow: hidden;
border-radius: 4px;
flex: 1 1 100%;
}
.found-breaches .listing-wrapper {
display: inline-flex;
justify-content: space-between;
flex-wrap: wrap;
flex-direction: row;
}
.found-breaches .listing-wrapper .breach-listing {
max-width: calc(50% - 1rem);
flex: 1 1 calc(50% - 1rem);
}
.breach-listing .breach-logo-title {
width: 100%;
padding: 1rem 2rem;
padding: 0.5rem 2rem;
border-bottom: 1px solid #eee;
}
@ -31,33 +10,27 @@
.breach-listing .logo-wrapper {
display: inline-block;
}
.breach-listing .logo-wrapper {
min-width: 1rem;
max-width: 1rem;
width: 1rem;
height: 1rem;
margin-right: .25rem;
}
margin-right: 0.25rem;
}
img.breach-logo {
max-height: 1rem;
max-width: 1rem;
}
h4.breach-title.key {
font-size: .9rem;
}
h4.breach-title.key,
.breach-listing a,
.breach-info {
display: block;
font-size: .9rem;
font-size: 0.85rem;
}
.breach-info {
line-height: 1.65rem;
line-height: 150%;
}
h4.breach-title,
@ -66,12 +39,12 @@ h4.breach-title,
}
.breach-info .key {
margin-right: .25rem;
margin-right: 0.25rem;
}
.breach-logo-title,
.breach-info {
margin-bottom: .5rem;
margin-bottom: 0.5rem;
}
.breach-listing a {
@ -79,26 +52,12 @@ h4.breach-title,
text-decoration: underline;
}
@media screen and (max-width: 800px) {
.found-breaches .row {
flex-wrap: wrap;
}
.found-breaches .breach-listing {
margin-bottom: var(--padding);
flex: 1 1 100%;
max-width: 100%;
margin-bottom: var(--padding);
}
}
@media screen and (max-width: 500px) {
.breach-info-wrap {
padding: 1rem 1rem 2rem 1rem;
}
.breach-logo-title.logo-title-wrapper {
padding: 1rem;
padding: 0 1rem;
}
}

Просмотреть файл

@ -0,0 +1,47 @@
.breach-stat-number {
align-items: center;
font-size: 2rem;
width: 3rem;
height: 3rem;
justify-content: center;
border-right: 1px solid rgba(219, 219, 219, 0.9);
margin: 0.15rem;
}
.stat-subhead {
font-size: 0.7rem;
}
.stat-headline {
text-transform: uppercase;
letter-spacing: 0.5px;
font-size: 0.8rem;
}
.breach-stats {
background-color: rgba(255, 255, 255, 0);
border: 1px solid rgba(219, 219, 219, 0.9);
border-radius: 2px;
overflow: hidden;
flex-direction: column-reverse;
margin-top: 2rem;
}
.breach-stats > * {
margin-bottom: 0;
}
.breach-stat-row {
width: 100%;
border-bottom: 1px solid rgba(219, 219, 219, 0.9);
}
.breach-stats:last-child {
border-bottom: 0;
}
.breach-stat-label {
padding-left: 1rem;
justify-content: center;
flex-direction: column;
}

Просмотреть файл

@ -1,6 +1,7 @@
footer {
border-top: 1px solid #eee;
width:100%;
width: 100%;
margin: auto auto 0 auto;
}
svg.Mozilla-logo {
@ -29,6 +30,6 @@ svg.Mozilla-logo {
@media screen and (max-width: 500px) {
footer {
padding: .75rem 0;
padding: 0.75rem 0;
}
}

Просмотреть файл

@ -7,11 +7,6 @@ input::placeholder {
font-size: 15px;
}
/* prevents zoom on ios devices */
input[type="email"] {
font-size: 17px;
}
input[type="submit"],
input[type="email"] {
height: 4rem;
@ -23,8 +18,10 @@ input[type="email"] {
}
input[type="email"] {
text-indent: .5rem;
background-color: rgba(255, 255, 255, 1);
/* prevents zoom on ios devices */
font-size: 17px;
text-indent: 0.5rem;
background-color: rgba(255, 255, 255, 0);
border: 1px solid rgba(0, 0, 0, 0.13);
margin-bottom: var(--margin);
}
@ -41,7 +38,7 @@ button:focus,
.radio-button-group:focus {
border: 1px solid var(--blue50);
border: 1px solid rgb(40, 97, 205);
box-shadow: 0 0 0 1px rgb(63, 97, 217), 0 0 0 4px rgba(63, 97, 217, .3);
box-shadow: 0 0 0 1px rgb(63, 97, 217), 0 0 0 4px rgba(63, 97, 217, 0.3);
outline: none;
}
@ -123,7 +120,7 @@ button:focus,
}
.form-desc {
font-size: .8rem;
font-size: 0.8rem;
font-weight: 300;
color: rgba(36, 34, 45, 0.6);
max-width: 300px;

Просмотреть файл

@ -2,11 +2,6 @@ header {
border-bottom: 1px solid rgba(238, 238, 238, 1);
}
button.sign-in {
height: 32px;
border: 1px solid rgba(223, 0, 255, 0.24);
}
h1.fx-monitor {
font-size: 1.7rem;
font-weight: 600;
@ -34,11 +29,8 @@ nav {
}
a.nav-link {
padding-right: calc(1rem + 1vw);
padding-right: calc(1rem + 1vw);
padding-left: calc(1rem + 1vw);
}
a.nav-link {
text-align: center;
justify-content: center;
}
@ -88,6 +80,7 @@ nav.mobile-menu a:hover {
.fxa-menu-wrapper {
cursor: pointer;
margin-left: 1rem;
position: relative;
}
.avatar-wrapper,
@ -106,10 +99,6 @@ img.avatar {
z-index: 2;
}
.fxa-menu-wrapper {
position: relative;
}
.fxa-menu-links {
background-color: rgba(255, 255, 255, 1);
border-radius: 3px;

Просмотреть файл

@ -4,17 +4,18 @@
margin: auto;
}
.latest-breach.container {
background-color: rgba(255, 255, 255, 1);
border-bottom: 1px solid #eee;
}
.latest-breach .desc {
.latest-breach h3.subhead {
padding: 0 0 0 0;
text-align: center;
display: block;
margin-bottom: 2rem;
margin: auto auto 2rem auto;
}
.latest-breach .row {
flex-direction: column;
box-shadow: 1px 1px 10px #eeeeee4d;
}
.latest-breach {
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 50%, white 50%, white 100%); /* W3C */
}

Просмотреть файл

@ -1,7 +1,3 @@
h3.feature-title {
margin-bottom: .5rem;
}
.monitor-features {
background: rgb(27, 26, 29);
color: rgba(255, 255, 255, 1);
@ -14,6 +10,7 @@ h3.feature-title {
}
h3.feature-title {
margin-bottom: 0.5rem;
font-weight: 500;
}
@ -32,7 +29,7 @@ h4.feature-subhead {
.feat-img {
height: 4rem;
width: 4rem;
border: 1px solid rgba(255, 255, 255, .1);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 50%;
margin: 1rem auto;
background-color: rgba(255, 255, 255, 0);
@ -41,7 +38,7 @@ h4.feature-subhead {
.monitor-features .content:hover .feat-img,
.feat-img:hover {
background-color: rgba(255, 255, 255, .08);
background-color: rgba(255, 255, 255, 0.08);
transition: all 0.3s ease;
}

Просмотреть файл

@ -1,3 +1,7 @@
main.container.monitor-homepage {
min-height: 65vh;
}
.homepage-scan-form {
border: 1px solid #eee;
border-radius: 3px;

Просмотреть файл

@ -0,0 +1,26 @@
.found-breaches .breach-listing {
border: 1px solid #eee;
overflow: hidden;
border-radius: 4px;
flex: 1 1 40%;
margin: 2.5rem;
}
.found-breaches {
display: inline-flex;
justify-content: space-between;
flex-wrap: wrap;
flex-direction: row;
}
.show-additional-breaches {
flex-wrap: wrap;
}
@media screen and (max-width: 800px) {
.found-breaches .breach-listing {
margin-bottom: var(--padding);
flex: 1 1 100%;
max-width: 100%;
}
}

8
public/css/subpage.css Normal file
Просмотреть файл

@ -0,0 +1,8 @@
.subpage {
margin: auto;
}
.subpage .content-box {
flex-direction: column;
justify-content: center;
}

Просмотреть файл

@ -1,124 +1,124 @@
/* eslint-env browser */
"use strict";
/* global ga */
/* global ga_getLocation */
// /* eslint-env browser */
// "use strict";
// /* global ga */
// /* global ga_getLocation */
const hasParent = (el, selector) => {
while (el.parentNode) {
el = el.parentNode;
if (el.id === selector)
return el;
}
return null;
};
// const hasParent = (el, selector) => {
// while (el.parentNode) {
// el = el.parentNode;
// if (el.id === selector)
// return el;
// }
// return null;
// };
const setMetricsIds = (el) => {
if (hasParent(el, "scan-another-email")) {
el.dataset.eventCategory = "Scan Another Email Form";
}
if (el.dataset.entrypoint && hasParent(el, "sign-up-banner")) {
el.dataset.eventCategory = `${el.dataset.eventCategory} - Banner`;
el.dataset.entrypoint = `${el.dataset.entrypoint}-banner`;
}
return;
};
// const setMetricsIds = (el) => {
// if (hasParent(el, "scan-another-email")) {
// el.dataset.eventCategory = "Scan Another Email Form";
// }
// if (el.dataset.entrypoint && hasParent(el, "sign-up-banner")) {
// el.dataset.eventCategory = `${el.dataset.eventCategory} - Banner`;
// el.dataset.entrypoint = `${el.dataset.entrypoint}-banner`;
// }
// return;
// };
const getLocation = () => {
const eventLocation = document.querySelectorAll("[data-page-label]");
if (eventLocation.length > 0) {
return `Page ID: ${eventLocation[0].dataset.pageLabel}`;
} else {
return `Page ID: ${ga_getLocation()}`;
}
};
// const getLocation = () => {
// const eventLocation = document.querySelectorAll("[data-page-label]");
// if (eventLocation.length > 0) {
// return `Page ID: ${eventLocation[0].dataset.pageLabel}`;
// } else {
// return `Page ID: ${ga_getLocation()}`;
// }
// };
const sendPing = async(el, eventAction, eventLabel = null) => {
if (typeof(ga) !== "undefined" && !el.classList.contains("hide")) {
if (!eventLabel) {
eventLabel = `${getLocation()}`;
}
const eventCategory = `[v2] ${el.dataset.eventCategory}`;
if (eventCategory.includes("Scan")) {
// Append user status to eventLabel for scan form events.
eventLabel = `${eventLabel} [Signed in user: ${document.body.dataset.signedInUser}]`;
}
return ga("send", "event", eventCategory, eventAction, eventLabel);
}
};
// const sendPing = async(el, eventAction, eventLabel = null) => {
// if (typeof(ga) !== "undefined" && !el.classList.contains("hide")) {
// if (!eventLabel) {
// eventLabel = `${getLocation()}`;
// }
// const eventCategory = `[v2] ${el.dataset.eventCategory}`;
// if (eventCategory.includes("Scan")) {
// // Append user status to eventLabel for scan form events.
// eventLabel = `${eventLabel} [Signed in user: ${document.body.dataset.signedInUser}]`;
// }
// return ga("send", "event", eventCategory, eventAction, eventLabel);
// }
// };
const getFxaUtms = (url) => {
const utmSource = encodeURIComponent(document.body.dataset.serverUrl.replace(/(^\w+:|^)\/\//g, ""));
url.searchParams.append("utm_source", utmSource);
url.searchParams.append("utm_campaign", document.body.dataset.utmCampaign);
url.searchParams.append("form_type", "email");
return url;
};
// const getFxaUtms = (url) => {
// const utmSource = encodeURIComponent(document.body.dataset.serverUrl.replace(/(^\w+:|^)\/\//g, ""));
// url.searchParams.append("utm_source", utmSource);
// url.searchParams.append("utm_campaign", document.body.dataset.utmCampaign);
// url.searchParams.append("form_type", "email");
// return url;
// };
(() => {
// Update data-event-category and data-fxa-entrypoint if the element
// is nested inside a sign up banner.
document.querySelectorAll("#scan-user-email, .open-oauth").forEach(el => {
setMetricsIds(el);
});
// (() => {
// // Update data-event-category and data-fxa-entrypoint if the element
// // is nested inside a sign up banner.
// document.querySelectorAll("#scan-user-email, .open-oauth").forEach(el => {
// setMetricsIds(el);
// });
let fxaUrl = new URL("/metrics-flow?", document.body.dataset.fxaAddress);
fxaUrl = getFxaUtms(fxaUrl);
// let fxaUrl = new URL("/metrics-flow?", document.body.dataset.fxaAddress);
// fxaUrl = getFxaUtms(fxaUrl);
document.querySelectorAll(".open-oauth").forEach( async(el) => {
fxaUrl.searchParams.append("entrypoint", encodeURIComponent(el.dataset.entrypoint));
const response = await fetch(fxaUrl, {credentials: "omit"});
// document.querySelectorAll(".open-oauth").forEach( async(el) => {
// fxaUrl.searchParams.append("entrypoint", encodeURIComponent(el.dataset.entrypoint));
// const response = await fetch(fxaUrl, {credentials: "omit"});
if (response.status === 200) {
const {flowId, flowBeginTime} = await response.json();
el.dataset.flowId = flowId;
el.dataset.flowBeginTime = flowBeginTime;
}
});
// if (response.status === 200) {
// const {flowId, flowBeginTime} = await response.json();
// el.dataset.flowId = flowId;
// el.dataset.flowBeginTime = flowBeginTime;
// }
// });
if (typeof(ga) !== "undefined") {
const pageLocation = getLocation();
// if (typeof(ga) !== "undefined") {
// const pageLocation = getLocation();
// Elements for which we send Google Analytics "View" pings...
const eventTriggers = [
"#scan-user-email",
"#dl-fx-bar",
"#dl-fx-banner",
"#fxa-new-user-bar",
"#show-additional-breaches",
".see-full-report-button",
".open-oauth",
".sign-up-button", // legacy sign up button, can be removed post-fxa
];
// // Elements for which we send Google Analytics "View" pings...
// const eventTriggers = [
// "#scan-user-email",
// "#dl-fx-bar",
// "#dl-fx-banner",
// "#fxa-new-user-bar",
// "#show-additional-breaches",
// ".see-full-report-button",
// ".open-oauth",
// ".sign-up-button", // legacy sign up button, can be removed post-fxa
// ];
// Send number of foundBreaches on Scan, Full Report, and User Dashboard pageviews
["Scan", "Full Report", "User Dashboard"].forEach(word => {
if (pageLocation.includes(word)) {
const breaches = document.querySelectorAll(".listings");
ga("send", "event", "[v2] Breach Count", "Returned Breaches", `${pageLocation}`, breaches.length);
}
});
// // Send number of foundBreaches on Scan, Full Report, and User Dashboard pageviews
// ["Scan", "Full Report", "User Dashboard"].forEach(word => {
// if (pageLocation.includes(word)) {
// const breaches = document.querySelectorAll(".listings");
// ga("send", "event", "[v2] Breach Count", "Returned Breaches", `${pageLocation}`, breaches.length);
// }
// });
// Send "View" pings and add event listeners.
document.querySelectorAll(eventTriggers).forEach(el => {
sendPing(el, "View", pageLocation);
if (["BUTTON", "A"].includes(el.tagName)) {
el.addEventListener("click", async(e) => {
await sendPing(el, "Engage", pageLocation);
});
}
});
// // Send "View" pings and add event listeners.
// document.querySelectorAll(eventTriggers).forEach(el => {
// sendPing(el, "View", pageLocation);
// if (["BUTTON", "A"].includes(el.tagName)) {
// el.addEventListener("click", async(e) => {
// await sendPing(el, "Engage", pageLocation);
// });
// }
// });
// Add event listeners to event triggering elements
// for which we do not send "View" pings.
document.querySelectorAll("[data-ga-link]").forEach((el) => {
el.addEventListener("click", async(e) => {
const linkId = `Link ID: ${e.target.dataset.eventLabel}`;
await sendPing(el, "Click", `${linkId} // ${pageLocation}`);
});
});
}
})();
// // Add event listeners to event triggering elements
// // for which we do not send "View" pings.
// document.querySelectorAll("[data-ga-link]").forEach((el) => {
// el.addEventListener("click", async(e) => {
// const linkId = `Link ID: ${e.target.dataset.eventLabel}`;
// await sendPing(el, "Click", `${linkId} // ${pageLocation}`);
// });
// });
// }
// })();

Просмотреть файл

@ -1,25 +1,32 @@
"use strict";
// open/close signed-in user fxa menu and set tabbing
const toggleMenu = (otherFocusableEls) => {
const toggleMenu = (otherFocusableEls, fxaMenuLinks) => {
document.body.classList.toggle("menu-open");
if (document.body.classList.contains("menu-open")) {
document.getElementById("close-menu").addEventListener("click", (e) => {
toggleMenu(otherFocusableEls);
toggleMenu(otherFocusableEls, fxaMenuLinks);
});
otherFocusableEls.forEach(el => {
el.tabIndex = -1;
});
fxaMenuLinks.forEach(link => {
link.tabIndex = 0;
});
} else {
otherFocusableEls.forEach(el => {
el.tabIndex = 0;
});
fxaMenuLinks.forEach(link => {
link.tabIndex = -1;
});
}
};
if (document.querySelector("#avatar-wrapper")) {
const avatar = document.getElementById("avatar-wrapper");
const otherFocusableEls = document.querySelectorAll("button, a:not(.fxa-menu-link), input");
const fxaMenuLinks = document.querySelectorAll(".fxa-menu-link");
avatar.addEventListener("focus", () => {
avatar.addEventListener("keydown", (e) => {
@ -27,23 +34,24 @@ if (document.querySelector("#avatar-wrapper")) {
if ([32, 13].includes(e.keyCode)) {
e.preventDefault(); // prevents page from jumping or scrolling down
e.stopImmediatePropagation();
return toggleMenu(otherFocusableEls);
return toggleMenu(otherFocusableEls, fxaMenuLinks);
}
// close menu on escape (keyCode:27) clicks
if (e.keyCode === 27 && document.body.classList.contains("menu-open")) {
return toggleMenu(otherFocusableEls);
return toggleMenu(otherFocusableEls, fxaMenuLinks);
}
});
});
const fxaMenuLinks = document.querySelectorAll(".fxa-menu-link");
fxaMenuLinks.forEach(link => {
link.addEventListener("focus", (e) => {
link.addEventListener("keydown", (e) => {
link.addEventListener("keyup", (e) => {
if (e.keyCode === 27) {
toggleMenu(otherFocusableEls);
e.preventDefault();
e.stopImmediatePropagation();
toggleMenu(otherFocusableEls, fxaMenuLinks);
}
});
});
});
};
}

Просмотреть файл

@ -238,32 +238,6 @@ function checkBoxStates(checkBoxEvent) {
checkBox.checked = !checkBox.checked;
}
// async function sha1(message) {
// message = message.toLowerCase();
// const msgBuffer = new TextEncoder("utf-8").encode(message);
// let hashBuffer;
// if (/edge/i.test(navigator.userAgent)) {
// hashBuffer = libpolycrypt.sha1(msgBuffer);
// } else {
// hashBuffer = await crypto.subtle.digest("SHA-1", msgBuffer);
// }
// const hashArray = Array.from(new Uint8Array(hashBuffer));
// const hashHex = hashArray.map(b => ("00" + b.toString(16)).slice(-2)).join("");
// return hashHex.toUpperCase();
// }
// async function hashEmailAndSend(emailFormSubmitEvent) {
// const emailForm = emailFormSubmitEvent.target;
// ga_sendLegacyPing("Scan", false);
// emailForm.classList.add("loading-data");
// const emailInput = document.getElementById("scan-email");
// emailForm.querySelector("input[name=emailHash]").value = await sha1(emailInput.value);
// localStorage.setItem("scanned", emailInput.value);
// emailInput.value = "";
// sendPing(emailForm, "Success");
// emailForm.submit();
// }
const resendSubscribeData = function() {
ga_sendLegacyPing("Resend", false);
document.getElementById("confirm-your-account").classList.add("sending");
@ -320,11 +294,19 @@ const postData = (url, data = {}) => {
.catch(error => console.error(error));
};
function showAdditionalBreaches(){
document.getElementById("show-additional-breaches").classList.toggle("hide");
const toggleClasses = (classesToToggle, el) => {
classesToToggle.forEach(clss => {
el.classList.toggle(clss);
});
};
const showAdditionalBreaches = () => {
const showBreachesButton = document.getElementById("show-additional-breaches-wrapper");
const additionalBreaches = document.getElementById("additional-breaches");
additionalBreaches.classList.toggle("show-breaches");
}
[showBreachesButton, additionalBreaches].forEach(el => {
toggleClasses(["show", "hide"], el);
});
};
const handleRadioButtons = function(form) {
const inputFields = Array.from(form.querySelectorAll(".radio-button-group, .button"));

Просмотреть файл

@ -13,12 +13,12 @@ const getFooterLinks = (args) => {
{
title: "Frequently Asked Questions",
stringId: "faq",
href: "/faq",
href: "https://support.mozilla.org/kb/firefox-monitor-faq",
},
{
title: "Terms & Privacy",
stringId: "terms-and-privacy",
href: "/termsandprivacy",
href: "https://www.mozilla.org/privacy/firefox-monitor/?utm_campaign=fx_monitor_downloads&utm_content=site-footer-link&utm_medium=referral&utm_source=monitor.firefox.com",
},
{
title: "Mozilla.org",

Просмотреть файл

@ -8,12 +8,23 @@ const mozlog = require("./../log");
const log = mozlog("template-helpers/hbs-helpers");
const getSupportedLocales = (args) => {
if (args.data) {
return args.data.root.req.supportedLocales;
}
if (args.this) {
return args.this.req.supportedLocales;
}
return null;
};
function getString (id, args) {
const supportedLocales = args.data.root.req.supportedLocales;
const supportedLocales = getSupportedLocales(args);
return LocaleUtils.fluentFormat(supportedLocales, id, args.hash);
}
const getStrings = (stringArr, locales) => {
stringArr.forEach(string => {
const stringId = string.stringId;
@ -43,7 +54,7 @@ function getStringID (id, number, args) {
function localizedBreachDataClasses(dataClasses, args) {
const supportedLocales = args.data.root.req.supportedLocales;
const supportedLocales = getSupportedLocales(args);
const localizedDataClasses = [];
dataClasses.forEach(dataClass => {
localizedDataClasses.push(LocaleUtils.fluentFormat(supportedLocales, dataClass, args));
@ -80,7 +91,7 @@ function fluentNestedBold(id, args) {
function prettyDate(date, args) {
const supportedLocales = args.data.root.req.supportedLocales;
const supportedLocales = getSupportedLocales(args);
const jsDate = new Date(date);
const options = {year: "numeric", month: "long", day: "numeric"};
const intlDateTimeFormatter = new Intl.DateTimeFormat(supportedLocales, options);
@ -89,7 +100,7 @@ function prettyDate(date, args) {
function localeString(numericInput, args) {
const supportedLocales = args.data.root.req.supportedLocales;
const supportedLocales = getSupportedLocales(args);
const intlNumberFormatter = new Intl.NumberFormat(supportedLocales);
return intlNumberFormatter.format(numericInput);
}

Просмотреть файл

@ -6,6 +6,7 @@ const footer = require("./footer");
const header = require("./header");
const legacyHelpers = require("./hbs-helpers");
const monitorFeatures = require("./monitor-features");
const scanResults = require("./scan-results");
module.exports = {
@ -16,5 +17,6 @@ module.exports = {
header,
legacyHelpers,
monitorFeatures,
scanResults,
),
};

Просмотреть файл

@ -0,0 +1,51 @@
"use strict";
const { LocaleUtils } = require("./../locale-utils");
const breachStats = (args) => {
let foundBreaches = [];
const scanStats = {
monitoredEmails: {
headline: "email-addresses",
subhead: "being-monitored",
},
numBreaches: {
headline: "data-breaches",
subhead: "exposed-your-info",
},
passwords: {
headline: "passwords-exposed",
subhead: "across-all-breaches",
},
};
const locales = args.data.root.req.supportedLocales;
for (const stat in scanStats) {
// get translated strings for each category
for (const stringId in scanStats[stat]) {
const string = LocaleUtils.fluentFormat(locales, scanStats[stat][stringId]);
scanStats[stat][stringId] = string;
}
scanStats[stat]["count"] = 0;
}
// tally up found breaches
if (args.data.root.foundBreaches) {
foundBreaches = args.data.root.foundBreaches;
scanStats.numBreaches.count = foundBreaches.length;
}
// tally up breaches that exposed passwords
foundBreaches.forEach(breach => {
const dataClasses = breach.DataClasses;
if (dataClasses.includes("passwords")) {
scanStats.passwords.count++;
}
});
// return (args.fn(scanStats));
return scanStats;
};
module.exports = {
breachStats,
};

Просмотреть файл

@ -5,13 +5,13 @@
<div class="col-6">
<h2 class="big-headline">{{getString "landing-headline"}}</h2>
</div>
<div class="col-5 homepage-scan-form">
<div class="col-5 brdr">
<h3 class="main-subhead">{{getString "fxa-landing-blurb"}}</h3>
{{> scan_form }}
</div>
</section>
</main>
{{!-- {{> latest-breach }} --}}
{{> latest-breach }}
{{> article-list }}
{{> monitor-features }}

Просмотреть файл

@ -0,0 +1,13 @@
<section class="breach-stats">
{{#each (breachStats)}}
<div class="breach-stat-row flx">
<div class="breach-stat-number flx al-cntr bold">
{{ this.count }}
</div>
<div class="breach-stat-label flx">
<span class="stat-headline bold">{{ this.headline }}</span>
<span class="stat-subhead">{{ this.subhead }}</span>
</div>
</div>
{{/each}}
</section>

Просмотреть файл

@ -8,10 +8,10 @@
</div>
</div>
<div class="breach-info-wrap">
<span class="breach-info"><span class="key">{{getString "breach-added"}}</span>{{prettyDate AddedDate }}</span>
<span class="breach-info"><span class="key">{{getString "compromised-accounts"}}</span>{{localeString PwnCount}}</span>
<span class="breach-info"><span class="key">{{getString "breach-added" this}}</span>{{prettyDate AddedDate this}}</span>
<span class="breach-info"><span class="key">{{getString "compromised-accounts" this}}</span>{{localeString PwnCount this}}</span>
{{#if DataClasses }}
<span class="breach-info"><span class="key">{{getString "compromised-data"}}</span>{{localizedBreachDataClasses DataClasses }}</span>
<span class="breach-info"><span class="key">{{getString "compromised-data" this}}</span>{{localizedBreachDataClasses DataClasses this}}</span>
{{/if}}
<a href="/?breach={{Name}}" class="">{{getString "more-about-this-breach"}} &#8594;</a>
<a href="/?breach={{Name}}" class="">{{getString "more-about-this-breach" this}} &#8594;</a>
</div>

Просмотреть файл

@ -1,10 +1,10 @@
<section class="latest-breach container">
<section class="row">
<section class="row bg-white">
<div class="col-8">
<span class="desc">{{getString "latest-breach"}}</span>
<h3 class="subhead">{{getString "latest-breach"}}</h3>
<div class="breach-listing">
{{#lastAddedBreach}}
{{> breach_listing}}
{{> breach_listing this=./../this}}
{{/lastAddedBreach}}
</div>
</div>

Просмотреть файл

@ -4,7 +4,7 @@
<input type="hidden" name="pageToken" value="{{pageToken}}">
<input type="hidden" name="scannedEmailId" value="">
<div class="input-group">
<input id="scan-email" class="input-group-field email-to-hash" type="email" name="email" placeholder="{{getString "scan-placeholder"}}" aria-label="{{getString "scan-placeholder"}}" tabindex="0" autocomplete="off" />
<input id="scan-email" class="input-group-field email-to-hash" type="email" name="email" placeholder="{{getString "scan-placeholder"}}" aria-label="{{getString "scan-placeholder"}}" autocomplete="off" />
<span id="invalid-email-message" class="error-message">{{getString "scan-error"}}</span>
</div>
<input type="hidden" name="emailHash" />
@ -12,7 +12,7 @@
<input id="featured" type="hidden" name="featuredBreach" value="{{ featuredBreach.Name }}"/>
{{/if}}
<div class="input-group-button">
<input type="submit" class="button submit" value="{{fluentFxa "scan-submit"}}" tabindex="0"/>
<input type="submit" class="button submit" value="{{fluentFxa "scan-submit"}}"/>
<img class="loader" src="/img/loader.gif" alt="" />
</div>
</form>

Просмотреть файл

@ -9,6 +9,8 @@
<link rel="stylesheet" href="/css/latest-breach.css">
<link rel="stylesheet" href="/css/monitor.css">
<link rel="stylesheet" href="/css/monitor-features.css">
<link rel="stylesheet" href="/css/scan-results.css">
<link rel="stylesheet" href="/css/subpage.css">
{{else}}
<link rel="stylesheet" href="/dist/app.min.css">
{{/ifCompare}}

Просмотреть файл

@ -1,5 +1,32 @@
{{#if FXA_ENABLED}}
{{> fxa_enabled/fxa_scan}}
{{else}}
{{> legacy/scan}}
{{/if}}
<main class="container scan-results">
<div class="row">
<div class="col-6">
{{#if scannedEmailId }}
<p id="scanned-email-address">Results for <span id="scannedEmail" data-scanned-email-id={{ scannedEmailId }} class="bold"></span></p>
{{/if}}
<h2 id="scan-result-headline">{{{fluentNestedBold "guest-scan-results-headline" breachCount=foundBreaches.length}}}</h2>
{{> breach-stats }}
</div>
</div>
</main>
<section class="container bg-white">
<div class="row found-breaches">
{{#eachFromTo foundBreaches 0 4}}
<div class="breach-listing">
{{> breach_listing this= ./../this}}
</div>
{{/eachFromTo}}
{{#ifCompare foundBreaches.length ">" 4}}
<div id="show-additional-breaches-wrapper" class="col-12 show">
<button id="show-additional-breaches" class="utility-button" data-event-category="Show All Breaches Button">{{getString "show-all"}}</button>
</div>
<div id="additional-breaches" class="show-additional-breaches hide flx">
{{#eachFromTo foundBreaches 4 foundBreaches.length}}
<div class="breach-listing">
{{> breach_listing this= ./../this}}
</div>
{{/eachFromTo}}
</div>
{{/ifCompare}}
</div>
</section>

Просмотреть файл

@ -1,7 +1,7 @@
{{!< default }}
<section id="subpage" class="subpage" data-analytics-id="{{ analyticsID }}">
<section class="section-wrapper">
<section id="subpage" class="subpage container" data-analytics-id="{{ analyticsID }}">
<section class="content-box">
{{#ifCompare hash "&&" FXA_ENABLED}}
<h2 class="section-headline whole" >{{getString "fxa-unsub-headline"}}</h2>
<p class="sub-head whole">
@ -11,8 +11,8 @@
</a>
</p>
{{else}}
<h2 class="section-headline whole" >{{{ headline }}}</h2>
<p class="sub-head whole">{{{ subhead }}}</p>
<h2 class="subpage-headline" >{{{ headline }}}</h2>
<p class="subpage-subhead">{{{ subhead }}}</p>
{{/ifCompare}}
{{#if whichPartial}}
{{> (lookup . 'whichPartial') }}