diff --git a/api-server/server/component-passport.js b/api-server/server/component-passport.js index c41ba43691..1245b60695 100644 --- a/api-server/server/component-passport.js +++ b/api-server/server/component-passport.js @@ -83,9 +83,9 @@ export const loginRedirect = () => { const successRedirect = req => { if (!!req && req.session && req.session.returnTo) { delete req.session.returnTo; - return `${homeLocation}/welcome`; + return `${homeLocation}/`; } - return `${homeLocation}/welcome`; + return `${homeLocation}/`; }; let redirect = url.parse(successRedirect(req), true); @@ -112,7 +112,7 @@ export const createPassportCallbackAuthenticator = (strategy, config) => ( if (!user || !userInfo) { return res.redirect('/signin'); } - const redirect = `${homeLocation}/welcome`; + const redirect = `${homeLocation}/`; const { accessToken } = userInfo; const { provider } = config; diff --git a/api-server/server/passport-providers.js b/api-server/server/passport-providers.js index 1298a3d25e..7d0eff07b2 100644 --- a/api-server/server/passport-providers.js +++ b/api-server/server/passport-providers.js @@ -3,7 +3,7 @@ import { homeLocation, apiLocation } from '../../config/env'; const { clientID, clientSecret, domain } = auth0; -const successRedirect = `${homeLocation}/welcome`; +const successRedirect = `${homeLocation}/`; const failureRedirect = `${homeLocation}/signin`; export default { diff --git a/api-server/server/utils/middleware.js b/api-server/server/utils/middleware.js index fb796c7b36..18357497fb 100644 --- a/api-server/server/utils/middleware.js +++ b/api-server/server/utils/middleware.js @@ -55,7 +55,7 @@ export function ifNotVerifiedRedirectToUpdateEmail(req, res, next) { return next(); } -export function ifUserRedirectTo(path = `${homeLocation}/welcome`, status) { +export function ifUserRedirectTo(path = `${homeLocation}/`, status) { status = status === 302 ? 302 : 301; return (req, res, next) => { const { accessToken } = getAccessTokenFromRequest(req); diff --git a/client/src/components/Donation/Donation.css b/client/src/components/Donation/Donation.css index fafc82d351..8a20db1628 100644 --- a/client/src/components/Donation/Donation.css +++ b/client/src/components/Donation/Donation.css @@ -54,7 +54,6 @@ } .donation-email-container input { - color: var(--secondary-background); font-weight: normal; } diff --git a/client/src/components/Header/components/Login.js b/client/src/components/Header/components/Login.js index 4aa2534fde..467576bb67 100644 --- a/client/src/components/Header/components/Login.js +++ b/client/src/components/Header/components/Login.js @@ -26,7 +26,7 @@ const createOnClick = (navigate, isSignedIn) => e => { e.preventDefault(); gtagReportConversion(); if (isSignedIn) { - return gatsbyNavigate('/welcome'); + return gatsbyNavigate('/'); } return navigate(`${apiLocation}/signin`); }; diff --git a/client/src/components/Header/index.js b/client/src/components/Header/index.js index 80d37393fe..a70f7ffab5 100644 --- a/client/src/components/Header/index.js +++ b/client/src/components/Header/index.js @@ -20,7 +20,7 @@ function Header(props) { - {disableSettings ? null : } + diff --git a/client/src/components/landing/Landing.test.js b/client/src/components/landing/Landing.test.js new file mode 100644 index 0000000000..b43558ac0d --- /dev/null +++ b/client/src/components/landing/Landing.test.js @@ -0,0 +1,25 @@ +/* global expect */ +import React from 'react'; +import ShallowRenderer from 'react-test-renderer/shallow'; + +import { IndexPage } from '../../pages'; + +describe('', () => { + it('renders when visiting index page and logged out', () => { + const shallow = new ShallowRenderer(); + shallow.render(); + const result = shallow.getRenderOutput(); + expect(result.type.displayName === 'Landing').toBeTruthy(); + }); +}); + +const loggedOutProps = { + fetchState: { + complete: true, + error: null, + errored: false, + pending: false + }, + isSignedIn: false, + user: {} +}; diff --git a/client/src/components/landing/index.js b/client/src/components/landing/index.js new file mode 100644 index 0000000000..2954d37fa9 --- /dev/null +++ b/client/src/components/landing/index.js @@ -0,0 +1,72 @@ +import React, { Fragment } from 'react'; +import { Grid, Row, Col, Image } from '@freecodecamp/react-bootstrap'; +import Helmet from 'react-helmet'; + +import Login from '../Header/components/Login'; +import { Spacer } from '../helpers'; + +import './landing.css'; + +const BigCallToAction = () => ( + + + Sign in and get started. + + +); + +function Landing() { + return ( + + + Learn to code | freeCodeCamp.org + +
+ + + + +

+ Welcome to freeCodeCamp.org +

+ +

Learn to code.

+

+ Build projects and earn certifications. +

+

+ Grow your portfolio and get a developer job. +

+

+ It's all 100% free thanks to our nonprofit's donors. +

+ +
+ + + + companies featuring freeCodeCamp.org + + + +

+ Since 2014, more than 40,000 freeCodeCamp.org graduates have + gotten jobs in tech. +

+ +
+ +
+
+
+ ); +} + +Landing.displayName = 'Landing'; + +export default Landing; diff --git a/client/src/pages/index.css b/client/src/components/landing/landing.css similarity index 100% rename from client/src/pages/index.css rename to client/src/components/landing/landing.css diff --git a/client/src/components/layouts/Default.js b/client/src/components/layouts/Default.js index 748351d4f0..d490bb6faa 100644 --- a/client/src/components/layouts/Default.js +++ b/client/src/components/layouts/Default.js @@ -25,7 +25,6 @@ import Header from '../Header'; import Footer from '../Footer'; import './global.css'; -import './layout.css'; import './variables.css'; fontawesome.config = { @@ -67,7 +66,6 @@ const propTypes = { hasMessage: PropTypes.bool, isOnline: PropTypes.bool.isRequired, isSignedIn: PropTypes.bool, - landingPage: PropTypes.bool, onlineStatusChange: PropTypes.func.isRequired, pathname: PropTypes.string.isRequired, removeFlashMessage: PropTypes.func.isRequired, @@ -133,7 +131,6 @@ class DefaultLayout extends Component { flashMessage, isOnline, isSignedIn, - landingPage, removeFlashMessage, showFooter = true, theme @@ -157,11 +154,8 @@ class DefaultLayout extends Component { -
-
+
+
{hasMessage && flashMessage ? ( diff --git a/client/src/components/layouts/global.css b/client/src/components/layouts/global.css index 7412f114b6..1b3a8b722f 100644 --- a/client/src/components/layouts/global.css +++ b/client/src/components/layouts/global.css @@ -14,10 +14,6 @@ body { white-space: normal; } -.big-heading { - font-size: 50px !important; -} - .default-layout { margin-top: var(--header-height); background: var(--secondary-background); @@ -62,6 +58,33 @@ th { margin: 0 0 1.2rem; } +.big-heading { + font-size: 2.5rem !important; +} + +.medium-heading { + font-size: 1.5rem !important; + font-weight: normal; +} + +@media (max-width: 500px) { + .big-heading { + font-size: 1.6rem !important; + } + .medium-heading { + font-size: 1.4rem !important; + } + h1 { + font-size: 1.2rem; + } + h2 { + font-size: 1.1rem; + } + h3 { + font-size: 1rem; + } +} + .text-center { text-align: center !important; } @@ -351,3 +374,9 @@ pre { .nav-tabs > li > a { border-radius: 0; } + +blockquote footer, +blockquote small, +blockquote .small { + color: var(--gray-45); +} diff --git a/client/src/components/layouts/layout.css b/client/src/components/layouts/layout.css deleted file mode 100644 index 4846524024..0000000000 --- a/client/src/components/layouts/layout.css +++ /dev/null @@ -1,606 +0,0 @@ -/* html { - font-family: 'Lato', sans-serif; - -ms-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; -} -audio:not([controls]) { - display: none; - height: 0; -} -progress { - vertical-align: baseline; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline-width: 0; -} -abbr[title] { - border-bottom: none; - text-decoration: underline; - text-decoration: underline dotted; -} -b, -strong { - font-weight: inherit; - font-weight: bolder; -} -dfn { - font-style: italic; -} -h1 { - font-size: 2em; - margin: 0.67em 0; -} -mark { - background-color: #ff0; - color: #000; -} -small { - font-size: 80%; -} -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sub { - bottom: -0.25em; -} -sup { - top: -0.5em; -} -img { - border-style: none; -} -svg:not(:root) { - overflow: hidden; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -figure { - margin: 1em 40px; -} -hr { - box-sizing: content-box; - height: 0; - overflow: visible; -} -button, -input, -optgroup, -select, -textarea { - font: inherit; - margin: 0; -} -optgroup { - font-weight: 700; -} -button, -input { - overflow: visible; -} -button, -select { - text-transform: none; -} -[type='button']::-moz-focus-inner, -[type='reset']::-moz-focus-inner, -[type='submit']::-moz-focus-inner, -button::-moz-focus-inner { - border-style: none; - padding: 0; -} -[type='button']:-moz-focusring, -[type='reset']:-moz-focusring, -[type='submit']:-moz-focusring, -button:-moz-focusring { - outline: 1px dotted ButtonText; -} -fieldset { - border: 1px solid silver; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} -legend { - box-sizing: border-box; - color: inherit; - display: table; - max-width: 100%; - padding: 0; - white-space: normal; -} -textarea { - overflow: auto; -} -[type='checkbox'], -[type='radio'] { - box-sizing: border-box; - padding: 0; -} -[type='number']::-webkit-inner-spin-button, -[type='number']::-webkit-outer-spin-button { - height: auto; -} -[type='search'] { - -webkit-appearance: textfield; - outline-offset: -2px; -} -[type='search']::-webkit-search-cancel-button, -[type='search']::-webkit-search-decoration { - -webkit-appearance: none; -} -::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; -} -::-webkit-file-upload-button { - -webkit-appearance: button; - font: inherit; -} -html { - font: 112.5%/1.45em georgia, serif; - box-sizing: border-box; - overflow-y: scroll; -} -* { - box-sizing: inherit; -} -*:before { - box-sizing: inherit; -} -*:after { - box-sizing: inherit; -} -body { - color: hsla(0, 0%, 0%, 0.8); - font-family: 'Lato', sans-serif; - font-weight: normal; - word-wrap: break-word; - font-kerning: normal; - -moz-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; - -webkit-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; - font-feature-settings: 'kern', 'liga', 'clig', 'calt'; -} -img { - max-width: 100%; - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -h1 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 2.25rem; - line-height: 1.1; -} -h2 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 1.62671rem; - line-height: 1.1; -} -h3 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 1.38316rem; - line-height: 1.1; -} -h4 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 1rem; - line-height: 1.1; -} -h5 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 0.85028rem; - line-height: 1.1; -} -h6 { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - color: inherit; - font-family: 'Lato', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - text-rendering: optimizeLegibility; - font-size: 0.78405rem; - line-height: 1.1; -} -hgroup { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -ul { - margin-left: 1.45rem; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - list-style-position: outside; - list-style-image: none; -} -ol { - margin-left: 1.45rem; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - list-style-position: outside; - list-style-image: none; -} -dl { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -dd { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -p { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -figure { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -pre { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - font-size: 0.85rem; - line-height: 1.42; - background: hsla(0, 0%, 0%, 0.04); - border-radius: 3px; - overflow: auto; - word-wrap: normal; - padding: 1.45rem; -} -table { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; - font-size: 1rem; - line-height: 1.45rem; - border-collapse: collapse; - width: 100%; -} -fieldset { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -blockquote { - margin-left: 1.45rem; - margin-right: 1.45rem; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -form { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -noscript { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -iframe { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -hr { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: calc(1.45rem - 1px); - background-image: linear-gradient( - to right, - rgba(0, 0, 0, 0), - rgba(0, 0, 0, 0.75), - rgba(0, 0, 0, 0) - ); - border: none; - height: 1px; -} -address { - margin-left: 0; - margin-right: 0; - margin-top: 0; - padding-bottom: 0; - padding-left: 0; - padding-right: 0; - padding-top: 0; - margin-bottom: 1.45rem; -} -b { - font-weight: bold; -} -strong { - font-weight: bold; -} -dt { - font-weight: bold; -} -th { - font-weight: bold; -} -li { - margin-bottom: calc(1.45rem / 2); -} -ol li { - padding-left: 0; -} -ul li { - padding-left: 0; -} -li > ol { - margin-left: 1.45rem; - margin-bottom: calc(1.45rem / 2); - margin-top: calc(1.45rem / 2); -} -li > ul { - margin-left: 1.45rem; - margin-bottom: calc(1.45rem / 2); - margin-top: calc(1.45rem / 2); -} -blockquote *:last-child { - margin-bottom: 0; -} -li *:last-child { - margin-bottom: 0; -} -p *:last-child { - margin-bottom: 0; -} -li > p { - margin-bottom: calc(1.45rem / 2); -} -code { - font-size: 0.85rem; - line-height: 1.45rem; -} -kbd { - font-size: 0.85rem; - line-height: 1.45rem; -} -samp { - font-size: 0.85rem; - line-height: 1.45rem; -} -abbr { - border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); - cursor: help; -} -acronym { - border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); - cursor: help; -} -abbr[title] { - border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); - cursor: help; - text-decoration: none; -} -thead { - text-align: left; -} -td, -th { - text-align: left; - border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); - font-feature-settings: 'tnum'; - -moz-font-feature-settings: 'tnum'; - -webkit-font-feature-settings: 'tnum'; - padding-left: 0.96667rem; - padding-right: 0.96667rem; - padding-top: 0.725rem; - padding-bottom: calc(0.725rem - 1px); -} -th:first-child, -td:first-child { - padding-left: 0; -} -th:last-child, -td:last-child { - padding-right: 0; -} -tt, -code { - background-color: hsla(0, 0%, 0%, 0.04); - border-radius: 3px; - font-family: 'SFMono-Regular', Consolas, 'Roboto Mono', 'Droid Sans Mono', - 'Liberation Mono', Menlo, Courier, monospace; - padding: 0.2em 0.3em; -} -pre code { - background: none; - line-height: 1.42; -} -@media only screen and (max-width: 480px) { - html { - font-size: 100%; - } -} -.default-layout { - display: flex; - flex-direction: column; - margin-top: var(--header-height); - min-height: calc(100vh - var(--header-height)); -} */ diff --git a/client/src/components/welcome/Welcome.test.js b/client/src/components/welcome/Welcome.test.js new file mode 100644 index 0000000000..f5e212ad61 --- /dev/null +++ b/client/src/components/welcome/Welcome.test.js @@ -0,0 +1,37 @@ +/* global expect */ +import React from 'react'; +import renderer from 'react-test-renderer'; + +import 'jest-dom/extend-expect'; +import { IndexPage } from '../../pages'; + +import Welcome from './'; + +describe('', () => { + it('renders when visiting index page and logged in', () => { + const container = renderer + .create() + .toTree(); + expect(container.rendered.type.displayName === 'Welcome').toBeTruthy(); + }); + + it('has four links', () => { + const container = renderer.create() + .root; + expect(container.findAllByType('a').length === 4).toBeTruthy(); + }); +}); + +const loggedInProps = { + fetchState: { + complete: true, + error: null, + errored: false, + pending: false + }, + isSignedIn: true, + user: { + acceptedPrivacyTerms: true, + username: 'developmentuser' + } +}; diff --git a/client/src/components/welcome/index.js b/client/src/components/welcome/index.js new file mode 100644 index 0000000000..99621ef51a --- /dev/null +++ b/client/src/components/welcome/index.js @@ -0,0 +1,88 @@ +import React, { Fragment } from 'react'; +import { Grid, Row, Col } from '@freecodecamp/react-bootstrap'; +import Helmet from 'react-helmet'; +import PropTypes from 'prop-types'; + +import { Spacer, Link } from '../helpers'; +import { randomQuote } from '../../utils/get-words'; + +import './welcome.css'; + +function Welcome({ name }) { + const { quote, author } = randomQuote(); + return ( + + + Welcome | freeCodeCamp.org + +
+ + + + +

+ Welcome {name ? name : 'Camper'}! +

+ +
+ + + +
+ + {quote} +
+ {author} +
+
+
+ +
+ + + +

+ What would you like to do today? +

+ +
+ + + + + Build Projects and Earn Certifications + + + Update Your Developer Portfolio + + + Read Developer News + + + Help Developers on the Forum + + + + +
+
+
+ ); +} + +const propTypes = { + name: PropTypes.string +}; + +Welcome.propTypes = propTypes; +Welcome.displayName = 'Welcome'; + +export default Welcome; diff --git a/client/src/components/welcome/welcome.css b/client/src/components/welcome/welcome.css new file mode 100644 index 0000000000..099a0eada3 --- /dev/null +++ b/client/src/components/welcome/welcome.css @@ -0,0 +1,14 @@ +.quote-partial .blockquote { + font-size: 1.3rem; + border: none; +} + +@media (max-width: 500px) { + .quote-partial .blockquote { + font-size: 1.2rem; + border: none; + } +} +.quote-author { + font-style: normal; +} diff --git a/client/src/pages/accept-privacy-terms.js b/client/src/pages/accept-privacy-terms.js index 1acc263d20..3786b0e978 100644 --- a/client/src/pages/accept-privacy-terms.js +++ b/client/src/pages/accept-privacy-terms.js @@ -32,7 +32,7 @@ const mapStateToProps = createSelector( ); const mapDispatchToProps = dispatch => bindActionCreators({ acceptTerms }, dispatch); -const RedirectWelcome = createRedirect('/welcome'); +const RedirectHome = createRedirect('/'); class AcceptPrivacyTerms extends Component { constructor(props) { @@ -66,7 +66,7 @@ class AcceptPrivacyTerms extends Component { render() { const { acceptedPrivacyTerms } = this.props; if (acceptedPrivacyTerms) { - return ; + return ; } const { privacyPolicy, termsOfService, quincyEmail } = this.state; return ( diff --git a/client/src/pages/donate.js b/client/src/pages/donate.js index 07d398dac8..0b3e4c37b5 100644 --- a/client/src/pages/donate.js +++ b/client/src/pages/donate.js @@ -11,8 +11,6 @@ import DonateForm from '../components/Donation/components/DonateForm'; import DonateText from '../components/Donation/components/DonateText'; import PoweredByStripe from '../components/Donation/components/poweredByStripe'; -import './index.css'; - class DonatePage extends Component { constructor(...props) { super(...props); diff --git a/client/src/pages/index.js b/client/src/pages/index.js index 3a375718f5..479db8a597 100644 --- a/client/src/pages/index.js +++ b/client/src/pages/index.js @@ -1,240 +1,71 @@ -import React, { Fragment } from 'react'; -import { Grid, Row, Col, Image } from '@freecodecamp/react-bootstrap'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import React from 'react'; +import { createSelector } from 'reselect'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; + +import { Loader } from '../components/helpers'; +import Welcome from '../components/welcome'; +import Landing from '../components/landing'; import { - faHtml5, - faCss3Alt, - faJs, - faGithub, - faNodeJs, - faReact -} from '@fortawesome/free-brands-svg-icons'; -import { faDatabase } from '@fortawesome/free-solid-svg-icons'; -import Helmet from 'react-helmet'; + userSelector, + userFetchStateSelector, + isSignedInSelector +} from '../redux'; +import createRedirect from '../components/createRedirect'; -import { Link, Spacer } from '../components/helpers'; -import Login from '../components/Header/components/Login'; - -import './index.css'; - -const BigCallToAction = () => ( - - - Start coding (it's free) - - +const mapStateToProps = createSelector( + userFetchStateSelector, + isSignedInSelector, + userSelector, + (fetchState, isSignedIn, user) => ({ + fetchState, + isSignedIn, + user + }) ); -const IndexPage = () => ( - - - Learn to code | freeCodeCamp.org - - - - -

Learn to code for free.

- - - { -

- Join a supportive community of millions of coders. -

- - - Help nonprofits with pro bono code projects -

- Build projects and earn free certifications. -

- - - { -

Get experience by coding for nonprofits.

- -
- - - -

As featured in:

- companies featuring freeCodeCamp - -
- -

Launch your developer career

- - - - Meta's testimonial image -

- Through freeCodeCamp, I built a robust and highly functional web app - for a nonprofit. This led me to getting a fantastic job. -

-

- Meta Hirschl

- - - Brian's testimonial image -

- freeCodeCamp is a great way for disabled veterans like me to - retrain. I'm already receiving software engineering job offers. -

-

- Brian Grant

- - - Maxim Orlov's testimonial image -

- I joined freeCodeCamp with zero knowledge of web development. 6 - months later, I landed my first job as a back end engineer. -

-

- Maxim Orlov

- -
- -
- -

Learn powerful skills

- - - - -

HTML5

- - - -

CSS3

- - - -

JavaScript

- - - -

Databases

- -
- - - -

Git & GitHub

- - - -

Node.js

- - - -

React.js

- - - The D3.js Logo -

D3.js

- -
-
- -

- freeCodeCamp is a donor-supported tax-exempt 501(c)(3) nonprofit - organization (United States Federal Tax Identification Number: - 82-0779546) -

-

- Our mission: to help people learn to code for free. We accomplish this - by creating thousands of videos, articles, and interactive coding - lessons - all freely available to the public. We also have thousands of - freeCodeCamp study groups around the world. -

-

- Donations to freeCodeCamp go toward our education initiatives, and help - pay for servers, services, and staff. You can{' '} - - make a tax-deductible donation here - - . -

- - - -
-
-); +const RedirectAcceptPrivacyTerm = createRedirect('/accept-privacy-terms'); -export default IndexPage; +export const IndexPage = ({ + fetchState: { pending, complete }, + isSignedIn, + user: { acceptedPrivacyTerms, name = '' } +}) => { + if (pending && !complete) { + return ; + } + + if (isSignedIn && !acceptedPrivacyTerms) { + return ; + } + + if (isSignedIn) { + return ; + } + + return ; +}; + +const propTypes = { + fetchState: PropTypes.shape({ + pending: PropTypes.bool, + complete: PropTypes.bool, + errored: PropTypes.bool + }), + isSignedIn: PropTypes.bool, + user: PropTypes.shape({ + acceptedPrivacyTerms: PropTypes.bool, + completedCertCount: PropTypes.number, + completedChallengeCount: PropTypes.number, + completedLegacyCertCount: PropTypes.number, + completedProjectCount: PropTypes.number, + isDonating: PropTypes.bool, + name: PropTypes.string, + username: PropTypes.string + }) +}; + +IndexPage.propTypes = propTypes; +IndexPage.displayName = 'IndexPage'; + +export default connect(mapStateToProps)(IndexPage); diff --git a/client/src/pages/welcome.css b/client/src/pages/welcome.css deleted file mode 100644 index 40e108c59d..0000000000 --- a/client/src/pages/welcome.css +++ /dev/null @@ -1,22 +0,0 @@ -.quote-partial .blockquote { - font-size: 2.5rem; - border: none; -} - -.quote-author { - font-style: normal; -} - -.update-link { - text-decoration: underline; - font-size: 1.4em; - color: var(--secondary-color); -} - -p.stats { - font-size: 1.45rem; -} - -p.stats span { - color: var(--secondary-color); -} diff --git a/client/src/pages/welcome.js b/client/src/pages/welcome.js deleted file mode 100644 index f9850ba4cd..0000000000 --- a/client/src/pages/welcome.js +++ /dev/null @@ -1,163 +0,0 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { Grid, Row, Col } from '@freecodecamp/react-bootstrap'; -import Helmet from 'react-helmet'; - -import { CurrentChallengeLink, Loader, Spacer } from '../components/helpers'; -import Supporters from '../components/Supporters'; -import { - userSelector, - userFetchStateSelector, - isSignedInSelector, - activeDonationsSelector -} from '../redux'; -import { randomQuote } from '../utils/get-words'; -import createRedirect from '../components/createRedirect'; -import RedirectHome from '../components/RedirectHome'; - -import './welcome.css'; - -const propTypes = { - activeDonations: PropTypes.number, - fetchState: PropTypes.shape({ - pending: PropTypes.bool, - complete: PropTypes.bool, - errored: PropTypes.bool - }), - isSignedIn: PropTypes.bool, - user: PropTypes.shape({ - acceptedPrivacyTerms: PropTypes.bool, - completedCertCount: PropTypes.number, - completedChallengeCount: PropTypes.number, - completedLegacyCertCount: PropTypes.number, - completedProjectCount: PropTypes.number, - isDonating: PropTypes.bool, - name: PropTypes.string, - username: PropTypes.string - }) -}; - -const mapStateToProps = createSelector( - userFetchStateSelector, - isSignedInSelector, - userSelector, - activeDonationsSelector, - (fetchState, isSignedIn, user, activeDonations) => ({ - activeDonations, - fetchState, - isSignedIn, - user - }) -); -const mapDispatchToProps = dispatch => bindActionCreators({}, dispatch); -const RedirectAcceptPrivacyTerm = createRedirect('/accept-privacy-terms'); - -function Welcome({ - fetchState: { pending, complete }, - isSignedIn, - user: { - acceptedPrivacyTerms, - name = '', - completedChallengeCount: completedChallenges = 0, - completedProjectCount = 0, - completedCertCount = 0, - completedLegacyCertCount: completedLegacyCerts = 0, - isDonating - }, - activeDonations -}) { - if (pending && !complete) { - return ; - } - - if (!isSignedIn) { - return ; - } - - if (isSignedIn && !acceptedPrivacyTerms) { - return ; - } - - const { quote, author } = randomQuote(); - return ( - - - Welcome | freeCodeCamp.org - -
- - - - -

- Welcome {name ? name : 'Camper'}! -

- -
- - - - - - -
- - {quote} -
- {author} -
-
-
- -
- - - -

- You have completed {completedChallenges} of{' '} - 1408 coding challenges. -

-

- You have built {completedProjectCount} of{' '} - 30 projects. -

- {completedLegacyCerts ? ( -

- You have earned {completedLegacyCerts} of{' '} - 4 legacy certifications. -

- ) : null} -

- You have earned {completedCertCount} of{' '} - 6 certifications. -

- -
- - - - - Go to my next challenge - - - - -
-
-
- ); -} - -Welcome.displayName = 'Welcome'; -Welcome.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Welcome); diff --git a/client/src/redux/accept-terms-saga.js b/client/src/redux/accept-terms-saga.js index 76491fc22f..f8cb15ea69 100644 --- a/client/src/redux/accept-terms-saga.js +++ b/client/src/redux/accept-terms-saga.js @@ -18,7 +18,7 @@ function* acceptTermsSaga({ payload: quincyEmails }) { } function* acceptCompleteSaga() { - yield call(navigate, '/welcome'); + yield call(navigate, '/'); } export function createAcceptTermsSaga(types) { diff --git a/client/src/redux/settings/danger-zone-saga.js b/client/src/redux/settings/danger-zone-saga.js index 5df8cafce3..894aef043f 100644 --- a/client/src/redux/settings/danger-zone-saga.js +++ b/client/src/redux/settings/danger-zone-saga.js @@ -37,7 +37,7 @@ function* resetProgressSaga() { // wait for the refresh to complete yield take(appTypes.fetchUserComplete); // the complete action has been called - yield call(navigate, '/welcome'); + yield call(navigate, '/'); } catch (e) { yield put(resetProgressError(e)); } diff --git a/client/src/utils/handled-error.js b/client/src/utils/handled-error.js index 21e8f07025..5c91c3a2c5 100644 --- a/client/src/utils/handled-error.js +++ b/client/src/utils/handled-error.js @@ -20,7 +20,7 @@ export function wrapHandledError(err, { type, message, redirectTo }) { return err; } -export function handle400Error(e, options = { redirectTo: '/welcome' }) { +export function handle400Error(e, options = { redirectTo: '/' }) { const { response: { status } } = e; @@ -54,7 +54,7 @@ export function handle400Error(e, options = { redirectTo: '/welcome' }) { export function handle500Error( e, options = { - redirectTo: '/welcome' + redirectTo: '/' }, _reportClientSideError = reportClientSideError ) { diff --git a/client/utils/gatsby/layoutSelector.js b/client/utils/gatsby/layoutSelector.js index 29e81c932f..c2a1d48fdd 100644 --- a/client/utils/gatsby/layoutSelector.js +++ b/client/utils/gatsby/layoutSelector.js @@ -11,13 +11,6 @@ export default function layoutSelector({ element, props }) { const { location: { pathname } } = props; - if (pathname === '/') { - return ( - - {element} - - ); - } if (element.type === FourOhFourPage) { return {element}; }