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,9 +164,15 @@ class ShowCertification extends Component {
</div>
);
let donationSection = (
if (
userComplete &&
signedInUserName === username &&
!isDonating &&
!donationClosed
) {
conditionalDonationSection = (
<Grid className='donation-section'>
{!isDonationSubmitted && (
{!closeBtn && (
<Row>
<Col sm={10} smOffset={1} xs={12}>
<p>
@ -222,20 +186,21 @@ class ShowCertification extends Component {
</Row>
)}
<MinimalDonateForm
handleProcessing={this.handleProcessing}
showCloseBtn={this.showDonationCloseBtn}
defaultTheme='light'
/>
<Row>
<Col sm={4} smOffset={4} xs={6} xsOffset={3}>
{isDonationSubmitted && donationCloseBtn}
{closeBtn ? donationCloseBtn : ''}
</Col>
</Row>
</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: {
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: {
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