fix(client): move all user fetching to learn
This commit is contained in:
committed by
mrugesh
parent
ebe9c468e3
commit
f48952c3e6
@@ -1,6 +1,15 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { Loader } from '../../components/helpers';
|
||||||
|
import {
|
||||||
|
userSelector,
|
||||||
|
userFetchStateSelector,
|
||||||
|
isSignedInSelector
|
||||||
|
} from '../../redux';
|
||||||
|
import createRedirect from '../../components/createRedirect';
|
||||||
import DonateModal from '../Donation';
|
import DonateModal from '../Donation';
|
||||||
|
|
||||||
import 'prismjs/themes/prism.css';
|
import 'prismjs/themes/prism.css';
|
||||||
@@ -9,7 +18,33 @@ import './prism-night.css';
|
|||||||
import 'react-reflex/styles.css';
|
import 'react-reflex/styles.css';
|
||||||
import './learn.css';
|
import './learn.css';
|
||||||
|
|
||||||
function LearnLayout({ children }) {
|
const mapStateToProps = createSelector(
|
||||||
|
userFetchStateSelector,
|
||||||
|
isSignedInSelector,
|
||||||
|
userSelector,
|
||||||
|
(fetchState, isSignedIn, user) => ({
|
||||||
|
fetchState,
|
||||||
|
isSignedIn,
|
||||||
|
user
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const RedirectAcceptPrivacyTerm = createRedirect('/accept-privacy-terms');
|
||||||
|
|
||||||
|
function LearnLayout({
|
||||||
|
fetchState: { pending, complete },
|
||||||
|
isSignedIn,
|
||||||
|
user: { acceptedPrivacyTerms },
|
||||||
|
children
|
||||||
|
}) {
|
||||||
|
if (pending && !complete) {
|
||||||
|
return <Loader fullScreen={true} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSignedIn && !acceptedPrivacyTerms) {
|
||||||
|
return <RedirectAcceptPrivacyTerm />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<main id='learn-app-wrapper'>{children}</main>
|
<main id='learn-app-wrapper'>{children}</main>
|
||||||
@@ -19,6 +54,17 @@ function LearnLayout({ children }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LearnLayout.displayName = 'LearnLayout';
|
LearnLayout.displayName = 'LearnLayout';
|
||||||
LearnLayout.propTypes = { children: PropTypes.any };
|
LearnLayout.propTypes = {
|
||||||
|
children: PropTypes.any,
|
||||||
|
fetchState: PropTypes.shape({
|
||||||
|
pending: PropTypes.bool,
|
||||||
|
complete: PropTypes.bool,
|
||||||
|
errored: PropTypes.bool
|
||||||
|
}),
|
||||||
|
isSignedIn: PropTypes.bool,
|
||||||
|
user: PropTypes.shape({
|
||||||
|
acceptedPrivacyTerms: PropTypes.bool
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
export default LearnLayout;
|
export default connect(mapStateToProps)(LearnLayout);
|
||||||
|
@@ -16,7 +16,9 @@ describe('<Welcome />', () => {
|
|||||||
const shallow = new ShallowRenderer();
|
const shallow = new ShallowRenderer();
|
||||||
shallow.render(<LearnPage {...loggedInProps} />);
|
shallow.render(<LearnPage {...loggedInProps} />);
|
||||||
const result = shallow.getRenderOutput();
|
const result = shallow.getRenderOutput();
|
||||||
expect(result.type.displayName === 'LearnLayout').toBeTruthy();
|
expect(
|
||||||
|
result.type.WrappedComponent.displayName === 'LearnLayout'
|
||||||
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has a header', () => {
|
it('has a header', () => {
|
||||||
|
@@ -32,14 +32,6 @@ function Welcome({ name }) {
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<Col sm={10} smOffset={1} xs={12}>
|
|
||||||
<Spacer />
|
|
||||||
<h2 className='text-center medium-heading'>
|
|
||||||
What would you like to do today?
|
|
||||||
</h2>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
Grid,
|
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
Button,
|
Button,
|
||||||
@@ -74,87 +73,84 @@ class AcceptPrivacyTerms extends Component {
|
|||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Privacy Policy and Terms of Service | freeCodeCamp.org</title>
|
<title>Privacy Policy and Terms of Service | freeCodeCamp.org</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Grid>
|
<Spacer size={2} />
|
||||||
<Row>
|
<Row className='text-center'>
|
||||||
<Col xs={12}>
|
<Col sm={8} smOffset={2} xs={12}>
|
||||||
<div className='text-center'>
|
<h1>
|
||||||
<Spacer size={2} />
|
Please review our updated privacy policy and the terms of service.
|
||||||
<h3>
|
</h1>
|
||||||
Please review our updated privacy policy and the terms of
|
</Col>
|
||||||
service.
|
</Row>
|
||||||
</h3>
|
<Spacer size={2} />
|
||||||
|
<Row>
|
||||||
|
<Col sm={8} smOffset={2} xs={12}>
|
||||||
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
<FormGroup>
|
||||||
|
<ControlLabel htmlFor='terms-of-service'>
|
||||||
|
Terms of Service
|
||||||
|
</ControlLabel>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
</div>
|
<Checkbox
|
||||||
</Col>
|
checked={termsOfService}
|
||||||
</Row>
|
id='terms-of-service'
|
||||||
<Row>
|
inline={true}
|
||||||
<Col sm={6} smOffset={3}>
|
onChange={this.createHandleChange('termsOfService')}
|
||||||
<form onSubmit={this.handleSubmit}>
|
|
||||||
<FormGroup>
|
|
||||||
<ControlLabel htmlFor='terms-of-service'>
|
|
||||||
Terms of Service
|
|
||||||
</ControlLabel>
|
|
||||||
<Spacer />
|
|
||||||
<Checkbox
|
|
||||||
checked={termsOfService}
|
|
||||||
id='terms-of-service'
|
|
||||||
inline={true}
|
|
||||||
onChange={this.createHandleChange('termsOfService')}
|
|
||||||
>
|
|
||||||
I accept the{' '}
|
|
||||||
<Link external={true} to='/news/terms-of-service'>
|
|
||||||
terms of service
|
|
||||||
</Link>{' '}
|
|
||||||
(required)
|
|
||||||
</Checkbox>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup>
|
|
||||||
<ControlLabel htmlFor='privacy-policy'>
|
|
||||||
Privacy Policy
|
|
||||||
</ControlLabel>
|
|
||||||
<Spacer />
|
|
||||||
<Checkbox
|
|
||||||
checked={privacyPolicy}
|
|
||||||
id='privacy-policy'
|
|
||||||
inline={true}
|
|
||||||
onChange={this.createHandleChange('privacyPolicy')}
|
|
||||||
>
|
|
||||||
I accept the{' '}
|
|
||||||
<Link external={true} to='/news/privacy-policy'>
|
|
||||||
privacy policy
|
|
||||||
</Link>{' '}
|
|
||||||
(required)
|
|
||||||
</Checkbox>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup>
|
|
||||||
<ControlLabel htmlFor='quincy-email'>
|
|
||||||
Quincy's Emails
|
|
||||||
</ControlLabel>
|
|
||||||
<Spacer />
|
|
||||||
<Checkbox
|
|
||||||
checked={quincyEmail}
|
|
||||||
id='quincy-email'
|
|
||||||
inline={true}
|
|
||||||
onChange={this.createHandleChange('quincyEmail')}
|
|
||||||
>
|
|
||||||
I want weekly emails from Quincy, freeCodeCamp.org's
|
|
||||||
founder.
|
|
||||||
</Checkbox>
|
|
||||||
</FormGroup>
|
|
||||||
<ButtonSpacer />
|
|
||||||
<Button
|
|
||||||
block={true}
|
|
||||||
bsStyle='primary'
|
|
||||||
className='big-cta-btn'
|
|
||||||
disabled={!privacyPolicy || !termsOfService}
|
|
||||||
type='submit'
|
|
||||||
>
|
>
|
||||||
Continue to freeCodeCamp
|
I accept the{' '}
|
||||||
</Button>
|
<Link external={true} to='/news/terms-of-service'>
|
||||||
</form>
|
terms of service
|
||||||
</Col>
|
</Link>{' '}
|
||||||
</Row>
|
(required)
|
||||||
</Grid>
|
</Checkbox>
|
||||||
|
</FormGroup>
|
||||||
|
<Spacer />
|
||||||
|
<FormGroup>
|
||||||
|
<ControlLabel htmlFor='privacy-policy'>
|
||||||
|
Privacy Policy
|
||||||
|
</ControlLabel>
|
||||||
|
<Spacer />
|
||||||
|
<Checkbox
|
||||||
|
checked={privacyPolicy}
|
||||||
|
id='privacy-policy'
|
||||||
|
inline={true}
|
||||||
|
onChange={this.createHandleChange('privacyPolicy')}
|
||||||
|
>
|
||||||
|
I accept the{' '}
|
||||||
|
<Link external={true} to='/news/privacy-policy'>
|
||||||
|
privacy policy
|
||||||
|
</Link>{' '}
|
||||||
|
(required)
|
||||||
|
</Checkbox>
|
||||||
|
</FormGroup>
|
||||||
|
<Spacer />
|
||||||
|
<FormGroup>
|
||||||
|
<ControlLabel htmlFor='quincy-email'>
|
||||||
|
Quincy's Emails
|
||||||
|
</ControlLabel>
|
||||||
|
<Spacer />
|
||||||
|
<Checkbox
|
||||||
|
checked={quincyEmail}
|
||||||
|
id='quincy-email'
|
||||||
|
inline={true}
|
||||||
|
onChange={this.createHandleChange('quincyEmail')}
|
||||||
|
>
|
||||||
|
I want weekly emails from Quincy, freeCodeCamp.org's founder.
|
||||||
|
</Checkbox>
|
||||||
|
</FormGroup>
|
||||||
|
<ButtonSpacer />
|
||||||
|
<Button
|
||||||
|
block={true}
|
||||||
|
bsStyle='primary'
|
||||||
|
className='big-cta-btn'
|
||||||
|
disabled={!privacyPolicy || !termsOfService}
|
||||||
|
type='submit'
|
||||||
|
>
|
||||||
|
Continue to freeCodeCamp.org
|
||||||
|
</Button>
|
||||||
|
<Spacer size={2} />
|
||||||
|
</form>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,75 +1,28 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { graphql } from 'gatsby';
|
import { graphql } from 'gatsby';
|
||||||
|
|
||||||
import { Loader } from '../components/helpers';
|
|
||||||
import Landing from '../components/landing';
|
import Landing from '../components/landing';
|
||||||
import {
|
|
||||||
userSelector,
|
|
||||||
userFetchStateSelector,
|
|
||||||
isSignedInSelector
|
|
||||||
} from '../redux';
|
|
||||||
import createRedirect from '../components/createRedirect';
|
|
||||||
import { AllChallengeNode } from '../redux/propTypes';
|
import { AllChallengeNode } from '../redux/propTypes';
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
|
||||||
userFetchStateSelector,
|
|
||||||
isSignedInSelector,
|
|
||||||
userSelector,
|
|
||||||
(fetchState, isSignedIn, user) => ({
|
|
||||||
fetchState,
|
|
||||||
isSignedIn,
|
|
||||||
user
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const RedirectAcceptPrivacyTerm = createRedirect('/accept-privacy-terms');
|
|
||||||
const RedirectLearn = createRedirect('/learn');
|
|
||||||
|
|
||||||
export const IndexPage = ({
|
export const IndexPage = ({
|
||||||
fetchState: { pending, complete },
|
|
||||||
isSignedIn,
|
|
||||||
user: { acceptedPrivacyTerms },
|
|
||||||
data: {
|
data: {
|
||||||
allChallengeNode: { edges }
|
allChallengeNode: { edges }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
if (pending && !complete) {
|
|
||||||
return <Loader fullScreen={true} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSignedIn && !acceptedPrivacyTerms) {
|
|
||||||
return <RedirectAcceptPrivacyTerm />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSignedIn) {
|
|
||||||
return <RedirectLearn />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Landing edges={edges} />;
|
return <Landing edges={edges} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
data: PropTypes.shape({
|
data: PropTypes.shape({
|
||||||
allChallengeNode: AllChallengeNode
|
allChallengeNode: AllChallengeNode
|
||||||
}),
|
|
||||||
fetchState: PropTypes.shape({
|
|
||||||
pending: PropTypes.bool,
|
|
||||||
complete: PropTypes.bool,
|
|
||||||
errored: PropTypes.bool
|
|
||||||
}),
|
|
||||||
isSignedIn: PropTypes.bool,
|
|
||||||
user: PropTypes.shape({
|
|
||||||
acceptedPrivacyTerms: PropTypes.bool
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
IndexPage.propTypes = propTypes;
|
IndexPage.propTypes = propTypes;
|
||||||
IndexPage.displayName = 'IndexPage';
|
IndexPage.displayName = 'IndexPage';
|
||||||
|
|
||||||
export default connect(mapStateToProps)(IndexPage);
|
export default IndexPage;
|
||||||
|
|
||||||
export const query = graphql`
|
export const query = graphql`
|
||||||
query challNodes {
|
query challNodes {
|
||||||
|
@@ -14,7 +14,7 @@ import {
|
|||||||
|
|
||||||
import LearnLayout from '../components/layouts/Learn';
|
import LearnLayout from '../components/layouts/Learn';
|
||||||
import Login from '../components/Header/components/Login';
|
import Login from '../components/Header/components/Login';
|
||||||
import { Link, Spacer, Loader } from '../components/helpers';
|
import { Link, Spacer } from '../components/helpers';
|
||||||
import Map from '../components/Map';
|
import Map from '../components/Map';
|
||||||
import Welcome from '../components/welcome';
|
import Welcome from '../components/welcome';
|
||||||
import { dasherize } from '../../../utils/slugs';
|
import { dasherize } from '../../../utils/slugs';
|
||||||
@@ -80,7 +80,6 @@ const hashValueSelector = (state, hash) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const LearnPage = ({
|
export const LearnPage = ({
|
||||||
fetchState: { pending, complete },
|
|
||||||
location: { hash = '', state = '' },
|
location: { hash = '', state = '' },
|
||||||
isSignedIn,
|
isSignedIn,
|
||||||
user: { name = '' },
|
user: { name = '' },
|
||||||
@@ -92,12 +91,7 @@ export const LearnPage = ({
|
|||||||
allMarkdownRemark: { edges: mdEdges }
|
allMarkdownRemark: { edges: mdEdges }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
if (pending && !complete) {
|
|
||||||
return <Loader fullScreen={true} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hashValue = hashValueSelector(state, hash);
|
const hashValue = hashValueSelector(state, hash);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LearnLayout>
|
<LearnLayout>
|
||||||
<Helmet title='Learn | freeCodeCamp.org' />
|
<Helmet title='Learn | freeCodeCamp.org' />
|
||||||
|
Reference in New Issue
Block a user