Revert "feat(client): unify GA and add to donation" (#38001)

This reverts commit 78df306707.
This commit is contained in:
mrugesh
2020-01-01 12:04:50 +05:30
committed by GitHub
parent 89ddd4bb7e
commit 8e605d8b85
18 changed files with 108 additions and 303 deletions

View File

@ -15,8 +15,7 @@ import {
showCert,
userFetchStateSelector,
usernameSelector,
isDonatingSelector,
executeGA
isDonatingSelector
} from '../redux';
import validCertNames from '../../utils/validCertNames';
import { createFlashMessage } from '../components/Flash/redux';
@ -38,7 +37,6 @@ const propTypes = {
certDashedName: PropTypes.string,
certName: PropTypes.string,
createFlashMessage: PropTypes.func.isRequired,
executeGA: PropTypes.func,
fetchState: PropTypes.shape({
pending: PropTypes.bool,
complete: PropTypes.bool,
@ -76,20 +74,19 @@ const mapStateToProps = (state, { certName }) => {
};
const mapDispatchToProps = dispatch =>
bindActionCreators({ createFlashMessage, showCert, executeGA }, dispatch);
bindActionCreators({ createFlashMessage, showCert }, dispatch);
class ShowCertification extends Component {
constructor(...args) {
super(...args);
this.state = {
isDonationSubmitted: false,
isDonationDisplayed: false,
isDonationClosed: false
closeBtn: false,
donationClosed: false
};
this.hideDonationSection = this.hideDonationSection.bind(this);
this.handleProcessing = this.handleProcessing.bind(this);
this.showDonationCloseBtn = this.showDonationCloseBtn.bind(this);
}
componentDidMount() {
@ -100,53 +97,12 @@ class ShowCertification extends Component {
return null;
}
shouldComponentUpdate(nextProps) {
const {
userFetchState: { complete: userComplete },
signedInUserName,
isDonating,
cert: { username = '' },
executeGA
} = nextProps;
const { isDonationDisplayed } = this.state;
if (
!isDonationDisplayed &&
userComplete &&
signedInUserName === username &&
!isDonating
) {
this.setState({
isDonationDisplayed: true
});
executeGA({
type: 'event',
data: {
category: 'Donation',
action: 'Displayed Certificate Donation',
nonInteraction: true
}
});
}
return true;
}
hideDonationSection() {
this.setState({ isDonationDisplayed: false, isDonationClosed: true });
this.setState({ donationClosed: true });
}
handleProcessing(duration, amount) {
this.props.executeGA({
type: 'event',
data: {
category: 'donation',
action: 'certificate stripe form submission',
label: duration,
value: amount
}
});
this.setState({ isDonationSubmitted: true });
showDonationCloseBtn() {
this.setState({ closeBtn: true });
}
render() {
@ -155,14 +111,13 @@ class ShowCertification extends Component {
fetchState,
validCertName,
createFlashMessage,
certName
certName,
signedInUserName,
isDonating,
userFetchState
} = this.props;
const {
isDonationSubmitted,
isDonationDisplayed,
isDonationClosed
} = this.state;
const { donationClosed, closeBtn } = this.state;
if (!validCertName) {
createFlashMessage(standardErrorMessage);
@ -170,6 +125,7 @@ class ShowCertification extends Component {
}
const { pending, complete, errored } = fetchState;
const { complete: userComplete } = userFetchState;
if (pending) {
return <Loader fullScreen={true} />;
@ -193,6 +149,8 @@ class ShowCertification extends Component {
completionTime
} = cert;
let conditionalDonationSection = '';
const donationCloseBtn = (
<div>
<Button
@ -206,36 +164,43 @@ class ShowCertification extends Component {
</div>
);
let donationSection = (
<Grid className='donation-section'>
{!isDonationSubmitted && (
if (
userComplete &&
signedInUserName === username &&
!isDonating &&
!donationClosed
) {
conditionalDonationSection = (
<Grid className='donation-section'>
{!closeBtn && (
<Row>
<Col sm={10} smOffset={1} xs={12}>
<p>
Only you can see this message. Congratulations on earning this
certification. Its no easy task. Running freeCodeCamp isnt
easy either. Nor is it cheap. Help us help you and many other
people around the world. Make a tax-deductible supporting
donation to our nonprofit today.
</p>
</Col>
</Row>
)}
<MinimalDonateForm
showCloseBtn={this.showDonationCloseBtn}
defaultTheme='light'
/>
<Row>
<Col sm={10} smOffset={1} xs={12}>
<p>
Only you can see this message. Congratulations on earning this
certification. Its no easy task. Running freeCodeCamp isnt
easy either. Nor is it cheap. Help us help you and many other
people around the world. Make a tax-deductible supporting
donation to our nonprofit today.
</p>
<Col sm={4} smOffset={4} xs={6} xsOffset={3}>
{closeBtn ? donationCloseBtn : ''}
</Col>
</Row>
)}
<MinimalDonateForm
handleProcessing={this.handleProcessing}
defaultTheme='light'
/>
<Row>
<Col sm={4} smOffset={4} xs={6} xsOffset={3}>
{isDonationSubmitted && donationCloseBtn}
</Col>
</Row>
</Grid>
);
</Grid>
);
}
return (
<div className='certificate-outer-wrapper'>
{isDonationDisplayed && !isDonationClosed ? donationSection : ''}
{conditionalDonationSection}
<Grid className='certificate-wrapper certification-namespace'>
<Row>
<header>

View File

@ -34,7 +34,6 @@ const numToCommas = num =>
num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
const propTypes = {
handleProcessing: PropTypes.func,
isDonating: PropTypes.bool,
isSignedIn: PropTypes.bool,
navigate: PropTypes.func.isRequired,
@ -192,7 +191,7 @@ class DonateForm extends Component {
}
renderDonationOptions() {
const { stripe, handleProcessing } = this.props;
const { stripe } = this.props;
const { donationAmount, donationDuration, paymentType } = this.state;
return (
<div>
@ -204,7 +203,6 @@ class DonateForm extends Component {
donationAmount={donationAmount}
donationDuration={donationDuration}
getDonationButtonLabel={this.getDonationButtonLabel}
handleProcessing={handleProcessing}
hideAmountOptionsCB={this.hideAmountOptionsCB}
/>
</Elements>

View File

@ -24,7 +24,6 @@ const propTypes = {
donationDuration: PropTypes.string.isRequired,
email: PropTypes.string,
getDonationButtonLabel: PropTypes.func.isRequired,
handleProcessing: PropTypes.func,
isSignedIn: PropTypes.bool,
showCloseBtn: PropTypes.func,
stripe: PropTypes.shape({
@ -149,11 +148,8 @@ class DonateFormChildViewForHOC extends Component {
// change the donation modal button label to close
// or display the close button for the cert donation section
if (this.props.handleProcessing) {
this.props.handleProcessing(
this.state.donationDuration,
Math.round(this.state.donationAmount / 100)
);
if (this.props.showCloseBtn) {
this.props.showCloseBtn();
}
return postChargeStripe(yearEndGift, {

View File

@ -11,11 +11,11 @@ import Heart from '../../assets/icons/Heart';
import Cup from '../../assets/icons/Cup';
import MinimalDonateForm from './MinimalDonateForm';
import ga from '../../analytics';
import {
closeDonationModal,
isDonationModalOpenSelector,
isBlockDonationModalSelector,
executeGA
isBlockDonationModalSelector
} from '../../redux';
import { challengeMetaSelector } from '../../templates/Challenges/redux';
@ -36,8 +36,7 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
closeDonationModal,
executeGA
closeDonationModal
},
dispatch
);
@ -46,44 +45,18 @@ const propTypes = {
activeDonors: PropTypes.number,
block: PropTypes.string,
closeDonationModal: PropTypes.func.isRequired,
executeGA: PropTypes.func,
isBlockDonation: PropTypes.bool,
show: PropTypes.bool
};
function DonateModal({
show,
block,
isBlockDonation,
closeDonationModal,
executeGA
}) {
function DonateModal({ show, block, isBlockDonation, closeDonationModal }) {
const [closeLabel, setCloseLabel] = React.useState(false);
const handleProcessing = (duration, amount) => {
executeGA({
type: 'event',
data: {
category: 'donation',
action: 'Modal strip form submission',
label: duration,
value: amount
}
});
const showCloseBtn = () => {
setCloseLabel(true);
};
if (show) {
executeGA({ type: 'modal', data: '/donation-modal' });
executeGA({
type: 'event',
data: {
category: 'Donation',
action: `Displayed ${
isBlockDonation ? 'block' : 'progress'
} donation modal`,
nonInteraction: true
}
});
ga.modalview('/donation-modal');
}
const donationText = (
@ -128,7 +101,7 @@ function DonateModal({
<Modal.Body>
{isBlockDonation ? blockDonationText : progressDonationText}
<Spacer />
<MinimalDonateForm handleProcessing={handleProcessing} />
<MinimalDonateForm showCloseBtn={showCloseBtn} />
<Spacer />
<Row>
<Col sm={4} smOffset={4} xs={8} xsOffset={2}>

View File

@ -19,8 +19,8 @@ import './Donation.css';
const propTypes = {
defaultTheme: PropTypes.string,
handleProcessing: PropTypes.func,
isDonating: PropTypes.bool,
showCloseBtn: PropTypes.func,
stripe: PropTypes.shape({
createToken: PropTypes.func.isRequired
})
@ -79,7 +79,7 @@ class MinimalDonateForm extends Component {
render() {
const { donationAmount, donationDuration, stripe } = this.state;
const { handleProcessing, defaultTheme } = this.props;
const { showCloseBtn, defaultTheme } = this.props;
return (
<Row>
@ -93,7 +93,7 @@ class MinimalDonateForm extends Component {
getDonationButtonLabel={() =>
`Confirm your donation of $5 per month`
}
handleProcessing={handleProcessing}
showCloseBtn={showCloseBtn}
/>
</Elements>
</StripeProvider>

View File

@ -5,8 +5,9 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Link } from 'gatsby';
import ga from '../../../analytics';
import { makeExpandedBlockSelector, toggleBlock } from '../redux';
import { completedChallengesSelector, executeGA } from '../../../redux';
import { completedChallengesSelector } from '../../../redux';
import Caret from '../../../assets/icons/Caret';
import { blockNameify } from '../../../../utils/blockNameify';
import GreenPass from '../../../assets/icons/GreenPass';
@ -28,13 +29,12 @@ const mapStateToProps = (state, ownProps) => {
};
const mapDispatchToProps = dispatch =>
bindActionCreators({ toggleBlock, executeGA }, dispatch);
bindActionCreators({ toggleBlock }, dispatch);
const propTypes = {
blockDashedName: PropTypes.string,
challenges: PropTypes.array,
completedChallenges: PropTypes.arrayOf(PropTypes.string),
executeGA: PropTypes.func,
intro: PropTypes.shape({
fields: PropTypes.shape({ slug: PropTypes.string.isRequired }),
frontmatter: PropTypes.shape({
@ -58,25 +58,19 @@ export class Block extends Component {
}
handleBlockClick() {
const { blockDashedName, toggleBlock, executeGA } = this.props;
executeGA({
type: 'event',
data: {
category: 'Map Block Click',
action: blockDashedName
}
const { blockDashedName, toggleBlock } = this.props;
ga.event({
category: 'Map Block Click',
action: blockDashedName
});
return toggleBlock(blockDashedName);
}
handleChallengeClick(slug) {
return () => {
return this.props.executeGA({
type: 'event',
data: {
category: 'Map Challenge Click',
action: slug
}
return ga.event({
category: 'Map Challenge Click',
action: slug
});
};
}

View File

@ -44,7 +44,6 @@ test('<Block expanded snapshot', () => {
test('<Block /> should handle toggle clicks correctly', async () => {
const toggleSpy = jest.fn();
const toggleMapSpy = jest.fn();
const executeGA = jest.fn();
const props = {
blockDashedName: 'block-a',
@ -52,7 +51,6 @@ test('<Block /> should handle toggle clicks correctly', async () => {
completedChallenges: mockCompleted,
intro: mockIntroNodes[0],
isExpanded: false,
executeGA: executeGA,
toggleBlock: toggleSpy,
toggleMapModal: toggleMapSpy
};

View File

@ -26,10 +26,9 @@ const numToCommas = num =>
num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
const propTypes = {
handleProcessing: PropTypes.func,
showCloseBtn: PropTypes.func,
defaultTheme: PropTypes.string,
isDonating: PropTypes.bool,
executeGA: PropTypes.func,
stripe: PropTypes.shape({
createToken: PropTypes.func.isRequired
})
@ -48,7 +47,6 @@ class YearEndDonationForm extends Component {
this.handleSelectAmount = this.handleSelectAmount.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handlePaypalSubmission = this.handlePaypalSubmission.bind(this);
}
componentDidMount() {
@ -91,13 +89,14 @@ class YearEndDonationForm extends Component {
renderDonationOptions() {
const { donationAmount, stripe } = this.state;
const { handleProcessing, defaultTheme } = this.props;
const { showCloseBtn, defaultTheme } = this.props;
return (
<div>
<StripeProvider stripe={stripe}>
<Elements>
<DonateFormChildViewForHOC
handleProcessing={handleProcessing}
showCloseBtn={showCloseBtn}
defaultTheme={defaultTheme}
donationAmount={donationAmount}
donationDuration='onetime'
@ -180,23 +179,12 @@ class YearEndDonationForm extends Component {
);
}
handlePaypalSubmission() {
this.props.executeGA({
type: 'event',
data: {
category: 'donation',
action: 'year end gift paypal button click'
}
});
}
renderPayPalDonations() {
return (
<form
action='https://www.paypal.com/cgi-bin/webscr'
method='post'
target='_top'
onSubmit={this.handlePaypalSubmission}
>
<input type='hidden' name='cmd' value='_s-xclick' />
<input type='hidden' name='hosted_button_id' value='9C73W6CWSLNPW' />

View File

@ -2,7 +2,8 @@ import React, { Fragment, Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { fetchUser, isSignedInSelector, executeGA } from '../../redux';
import ga from '../../analytics';
import { fetchUser, isSignedInSelector } from '../../redux';
import { createSelector } from 'reselect';
const mapStateToProps = createSelector(
@ -12,7 +13,7 @@ const mapStateToProps = createSelector(
})
);
const mapDispatchToProps = { fetchUser, executeGA };
const mapDispatchToProps = { fetchUser };
class CertificationLayout extends Component {
componentDidMount() {
@ -20,7 +21,7 @@ class CertificationLayout extends Component {
if (!isSignedIn) {
fetchUser();
}
this.props.executeGA({ type: 'page', data: pathname });
ga.pageview(pathname);
}
render() {
return <Fragment>{this.props.children}</Fragment>;
@ -30,7 +31,6 @@ class CertificationLayout extends Component {
CertificationLayout.displayName = 'CertificationLayout';
CertificationLayout.propTypes = {
children: PropTypes.any,
executeGA: PropTypes.func,
fetchUser: PropTypes.func.isRequired,
isSignedIn: PropTypes.bool,
pathname: PropTypes.string.isRequired

View File

@ -6,13 +6,13 @@ import { createSelector } from 'reselect';
import Helmet from 'react-helmet';
import fontawesome from '@fortawesome/fontawesome';
import ga from '../../analytics';
import {
fetchUser,
isSignedInSelector,
onlineStatusChange,
isOnlineSelector,
userSelector,
executeGA
userSelector
} from '../../redux';
import { flashMessageSelector, removeFlashMessage } from '../Flash/redux';
@ -68,7 +68,6 @@ const metaKeywords = [
const propTypes = {
children: PropTypes.node.isRequired,
executeGA: PropTypes.func,
fetchUser: PropTypes.func.isRequired,
flashMessage: PropTypes.shape({
id: PropTypes.string,
@ -102,27 +101,27 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = dispatch =>
bindActionCreators(
{ fetchUser, removeFlashMessage, onlineStatusChange, executeGA },
{ fetchUser, removeFlashMessage, onlineStatusChange },
dispatch
);
class DefaultLayout extends Component {
componentDidMount() {
const { isSignedIn, fetchUser, pathname, executeGA } = this.props;
const { isSignedIn, fetchUser, pathname } = this.props;
if (!isSignedIn) {
fetchUser();
}
executeGA({ type: 'page', data: pathname });
ga.pageview(pathname);
window.addEventListener('online', this.updateOnlineStatus);
window.addEventListener('offline', this.updateOnlineStatus);
}
componentDidUpdate(prevProps) {
const { pathname, executeGA } = this.props;
const { pathname } = this.props;
const { pathname: prevPathname } = prevProps;
if (pathname !== prevPathname) {
executeGA({ type: 'page', data: pathname });
ga.pageview(pathname);
}
}

View File

@ -1,7 +1,6 @@
import React, { Component, Fragment } from 'react';
import Helmet from 'react-helmet';
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';
@ -10,11 +9,10 @@ import { stripePublicKey } from '../../config/env.json';
import { Spacer, Loader } from '../components/helpers';
import DonateForm from '../components/Donation/DonateForm';
import DonateText from '../components/Donation/DonateText';
import { signInLoadingSelector, userSelector, executeGA } from '../redux';
import { signInLoadingSelector, userSelector } from '../redux';
import { stripeScriptLoader } from '../utils/scriptLoaders';
const propTypes = {
executeGA: PropTypes.func,
isDonating: PropTypes.bool,
showLoading: PropTypes.bool.isRequired
};
@ -28,14 +26,6 @@ const mapStateToProps = createSelector(
})
);
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
executeGA
},
dispatch
);
export class DonatePage extends Component {
constructor(...props) {
super(...props);
@ -43,19 +33,11 @@ export class DonatePage extends Component {
stripe: null,
enableSettings: false
};
this.handleProcessing = this.handleProcessing.bind(this);
this.handleStripeLoad = this.handleStripeLoad.bind(this);
}
componentDidMount() {
this.props.executeGA({
type: 'event',
data: {
category: 'Donation',
action: `Displayed donate page`,
nonInteraction: true
}
});
if (window.Stripe) {
this.handleStripeLoad();
} else if (document.querySelector('#stripe-js')) {
@ -74,18 +56,6 @@ export class DonatePage extends Component {
}
}
handleProcessing(duration, amount) {
this.props.executeGA({
type: 'event',
data: {
category: 'donation',
action: 'donate page stripe form submission',
label: duration,
value: amount
}
});
}
handleStripeLoad() {
// Create Stripe instance once Stripe.js loads
console.info('stripe has loaded');
@ -118,7 +88,6 @@ export class DonatePage extends Component {
<Col md={6}>
<DonateForm
enableDonationSettingsPage={this.enableDonationSettingsPage}
handleProcessing={this.handleProcessing}
stripe={stripe}
/>
</Col>
@ -136,7 +105,4 @@ export class DonatePage extends Component {
DonatePage.displayName = 'DonatePage';
DonatePage.propTypes = propTypes;
export default connect(
mapStateToProps,
mapDispatchToProps
)(DonatePage);
export default connect(mapStateToProps)(DonatePage);

View File

@ -1,48 +1,11 @@
import React, { useEffect } from 'react';
import React from 'react';
import Helmet from 'react-helmet';
import { Grid } from '@freecodecamp/react-bootstrap';
import { connect } from 'react-redux';
import { executeGA } from '../redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import { Spacer, FullWidthRow } from '../components/helpers';
import YearEndDonationForm from '../components/YearEndGift/YearEndDonationForm';
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
executeGA
},
dispatch
);
const propTypes = {
executeGA: PropTypes.func
};
function YearEndGiftPage({ executeGA }) {
useEffect(() => {
executeGA({
type: 'event',
data: {
category: 'Donation',
action: `Displayed year end gift page`,
nonInteraction: true
}
});
}, [executeGA]);
const handleProcessing = (duration, amount) => {
executeGA({
type: 'event',
data: {
category: 'donation',
action: 'year-end-gift strip form submission',
label: duration,
value: amount
}
});
};
function YearEndGiftPage() {
return (
<>
<Helmet title='Support our nonprofit | freeCodeCamp.org' />
@ -50,11 +13,7 @@ function YearEndGiftPage({ executeGA }) {
<main>
<Spacer />
<FullWidthRow>
<YearEndDonationForm
defaultTheme='light'
executeGA={executeGA}
handleProcessing={handleProcessing}
/>
<YearEndDonationForm defaultTheme='light' />
</FullWidthRow>
<Spacer />
<Spacer />
@ -65,9 +24,5 @@ function YearEndGiftPage({ executeGA }) {
}
YearEndGiftPage.displayName = 'YearEndGiftPage';
YearEndGiftPage.propTypes = propTypes;
export default connect(
null,
mapDispatchToProps
)(YearEndGiftPage);
export default YearEndGiftPage;

View File

@ -1,11 +0,0 @@
import { takeEvery } from 'redux-saga/effects';
import ga from '../analytics';
function* callGaType({ payload: { type, data } }) {
const GaTypes = { event: ga.event, page: ga.pageview, modal: ga.modalview };
GaTypes[type](data);
}
export function createGaSaga(types) {
return [takeEvery(types.executeGA, callGaType)];
}

View File

@ -11,7 +11,6 @@ import { createReportUserSaga } from './report-user-saga';
import { createShowCertSaga } from './show-cert-saga';
import { createNightModeSaga } from './night-mode-saga';
import { createDonationSaga } from './donation-saga';
import { createGaSaga } from './ga-saga';
import hardGoToEpic from './hard-go-to-epic';
import failedUpdatesEpic from './failed-updates-epic';
@ -66,7 +65,6 @@ export const types = createTypes(
'onlineStatusChange',
'resetUserData',
'tryToShowDonationModal',
'executeGA',
'submitComplete',
'updateComplete',
'updateCurrentChallengeId',
@ -86,7 +84,6 @@ export const sagas = [
...createAcceptTermsSaga(types),
...createAppMountSaga(types),
...createDonationSaga(types),
...createGaSaga(types),
...createFetchUserSaga(types),
...createShowCertSaga(types),
...createReportUserSaga(types),
@ -98,9 +95,6 @@ export const appMount = createAction(types.appMount);
export const tryToShowDonationModal = createAction(
types.tryToShowDonationModal
);
export const executeGA = createAction(types.executeGA);
export const allowBlockDonationRequests = createAction(
types.allowBlockDonationRequests
);

View File

@ -6,8 +6,10 @@ import { createSelector } from 'reselect';
import { Button, Modal } from '@freecodecamp/react-bootstrap';
import { useStaticQuery, graphql } from 'gatsby';
import ga from '../../../analytics';
import Login from '../../../components/Header/components/Login';
import CompletionModalBody from './CompletionModalBody';
import { dasherize } from '../../../../../utils/slugs';
import './completion-modal.css';
@ -23,7 +25,7 @@ import {
lastBlockChalSubmitted
} from '../redux';
import { isSignedInSelector, executeGA } from '../../../redux';
import { isSignedInSelector } from '../../../redux';
const mapStateToProps = createSelector(
challengeFilesSelector,
@ -58,8 +60,7 @@ const mapDispatchToProps = function(dispatch) {
},
lastBlockChalSubmitted: () => {
dispatch(lastBlockChalSubmitted());
},
executeGA
}
};
return () => dispatchers;
};
@ -69,7 +70,6 @@ const propTypes = {
close: PropTypes.func.isRequired,
completedChallengesIds: PropTypes.array,
currentBlockIds: PropTypes.array,
executeGA: PropTypes.func,
files: PropTypes.object.isRequired,
id: PropTypes.string,
isOpen: PropTypes.bool,
@ -190,7 +190,7 @@ export class CompletionModalInner extends Component {
const { completedPercent } = this.state;
if (isOpen) {
executeGA({ type: 'modal', data: '/completion-modal' });
ga.modalview('/completion-modal');
}
const dashedName = dasherize(title);
return (

View File

@ -4,22 +4,21 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Button, Modal } from '@freecodecamp/react-bootstrap';
import ga from '../../../analytics';
import { createQuestion, closeModal, isHelpModalOpenSelector } from '../redux';
import { executeGA } from '../../../redux';
import './help-modal.css';
const mapStateToProps = state => ({ isOpen: isHelpModalOpenSelector(state) });
const mapDispatchToProps = dispatch =>
bindActionCreators(
{ createQuestion, executeGA, closeHelpModal: () => closeModal('help') },
{ createQuestion, closeHelpModal: () => closeModal('help') },
dispatch
);
const propTypes = {
closeHelpModal: PropTypes.func.isRequired,
createQuestion: PropTypes.func.isRequired,
executeGA: PropTypes.func,
isOpen: PropTypes.bool
};
@ -28,9 +27,9 @@ const RSA =
export class HelpModal extends Component {
render() {
const { isOpen, closeHelpModal, createQuestion, executeGA } = this.props;
const { isOpen, closeHelpModal, createQuestion } = this.props;
if (isOpen) {
executeGA({ type: 'modal', data: '/help-modal' });
ga.modalview('/help-modal');
}
return (
<Modal dialogClassName='help-modal' onHide={closeHelpModal} show={isOpen}>

View File

@ -5,14 +5,13 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Button, Modal } from '@freecodecamp/react-bootstrap';
import ga from '../../../analytics';
import { isResetModalOpenSelector, closeModal, resetChallenge } from '../redux';
import { executeGA } from '../../../redux';
import './reset-modal.css';
const propTypes = {
close: PropTypes.func.isRequired,
executeGA: PropTypes.func,
isOpen: PropTypes.bool.isRequired,
reset: PropTypes.func.isRequired
};
@ -26,11 +25,7 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
close: () => closeModal('reset'),
executeGA,
reset: () => resetChallenge()
},
{ close: () => closeModal('reset'), reset: () => resetChallenge() },
dispatch
);
@ -40,7 +35,7 @@ function withActions(...fns) {
function ResetModal({ reset, close, isOpen }) {
if (isOpen) {
executeGA({ type: 'modal', data: '/reset-modal' });
ga.modalview('/reset-modal');
}
return (
<Modal

View File

@ -4,30 +4,26 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Modal } from '@freecodecamp/react-bootstrap';
import ga from '../../../analytics';
import { closeModal, isVideoModalOpenSelector } from '../redux';
import { executeGA } from '../../../redux';
import './video-modal.css';
const mapStateToProps = state => ({ isOpen: isVideoModalOpenSelector(state) });
const mapDispatchToProps = dispatch =>
bindActionCreators(
{ closeVideoModal: () => closeModal('video'), executeGA },
dispatch
);
bindActionCreators({ closeVideoModal: () => closeModal('video') }, dispatch);
const propTypes = {
closeVideoModal: PropTypes.func.isRequired,
executeGA: propTypes.func,
isOpen: PropTypes.bool,
videoUrl: PropTypes.string
};
export class VideoModal extends Component {
render() {
const { isOpen, closeVideoModal, videoUrl, executeGA } = this.props;
const { isOpen, closeVideoModal, videoUrl } = this.props;
if (isOpen) {
executeGA({ type: 'modal', data: '/completion-modal' });
ga.modalview('/video-modal');
}
return (
<Modal