feat: a/b test lock icon (#45499)

* feat: a/b test

* Update client/i18n/locales/english/translations.json

* Apply suggestions from code review
This commit is contained in:
Ahmad Abdolsaheb
2022-03-22 19:28:41 +03:00
committed by GitHub
parent 4d620dea1a
commit 94650964c4
9 changed files with 39 additions and 94 deletions

View File

@ -52,7 +52,6 @@
"@reach/router": "1.3.4",
"@stripe/react-stripe-js": "1.7.0",
"@stripe/stripe-js": "1.25.0",
"@types/canvas-confetti": "1.4.2",
"@types/react-scrollable-anchor": "0.6.1",
"algoliasearch": "4.13.0",
"assert": "2.0.0",
@ -61,7 +60,6 @@
"bezier-easing": "2.1.0",
"browser-cookies": "1.2.0",
"buffer": "6.0.3",
"canvas-confetti": "1.5.1",
"chai": "4.3.6",
"crypto-browserify": "3.12.0",
"date-fns": "2.27.0",

View File

@ -23,7 +23,8 @@ import {
defaultDonationFormState,
userSelector,
postChargeStripe,
postChargeStripeCard
postChargeStripeCard,
isAVariantSelector
} from '../../redux';
import Spacer from '../helpers/spacer';
import { Themes } from '../settings/theme';
@ -33,6 +34,7 @@ import type { AddDonationData } from './paypal-button';
import PaypalButton from './paypal-button';
import StripeCardForm, { HandleAuthentication } from './stripe-card-form';
import WalletsWrapper from './walletsButton';
import SecurityLockIcon from './security-lock-icon';
import './donation.css';
@ -78,6 +80,7 @@ type DonateFormProps = {
) => string;
theme: Themes;
updateDonationFormState: (state: AddDonationData) => unknown;
isAVariant: boolean;
};
const mapStateToProps = createSelector(
@ -86,19 +89,22 @@ const mapStateToProps = createSelector(
isDonatingSelector,
donationFormStateSelector,
userSelector,
isAVariantSelector,
(
showLoading: DonateFormProps['showLoading'],
isSignedIn: DonateFormProps['isSignedIn'],
isDonating: DonateFormProps['isDonating'],
donationFormState: DonateFormState,
{ email, theme }: { email: string; theme: Themes }
{ email, theme }: { email: string; theme: Themes },
isAVariant: boolean
) => ({
isSignedIn,
isDonating,
showLoading,
donationFormState,
email,
theme
theme,
isAVariant
})
);
@ -315,7 +321,8 @@ class DonateForm extends Component<DonateFormProps, DonateFormComponentState> {
t,
isMinimalForm,
isSignedIn,
isDonating
isDonating,
isAVariant
} = this.props;
const priorityTheme = defaultTheme ? defaultTheme : theme;
const isOneTime = donationDuration === 'onetime';
@ -328,6 +335,7 @@ class DonateForm extends Component<DonateFormProps, DonateFormComponentState> {
return (
<>
<b className={isMinimalForm ? 'donation-label-modal' : ''}>
{isAVariant === false && <SecurityLockIcon />}
{this.getDonationButtonLabel()}:
</b>
<Spacer />
@ -366,6 +374,7 @@ class DonateForm extends Component<DonateFormProps, DonateFormComponentState> {
processing={processing}
t={t}
theme={priorityTheme}
isAVariant={isAVariant}
/>
</>
)}

View File

@ -334,6 +334,10 @@ li.disabled > a {
height: 22px;
}
.confirm-donation-btn svg.svg-inline--fa.fa-lock {
margin-bottom: 2px;
}
@media screen and (min-width: 355px) {
.form-payment-methods {
height: 30px;

View File

@ -0,0 +1,14 @@
import React from 'react';
import { faLock } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const SecurityLockIcon = (): JSX.Element => {
return (
<>
<FontAwesomeIcon icon={faLock} />
&nbsp;&nbsp;
</>
);
};
export default SecurityLockIcon;

View File

@ -17,6 +17,7 @@ import React, { useState } from 'react';
import envData from '../../../../config/env.json';
import { Themes } from '../settings/theme';
import { AddDonationData } from './paypal-button';
import SecurityLockIcon from './security-lock-icon';
const { stripePublicKey }: { stripePublicKey: string | null } = envData;
@ -34,6 +35,7 @@ interface FormPropTypes {
t: (label: string) => string;
theme: Themes;
processing: boolean;
isAVariant: boolean;
}
interface Element {
@ -49,7 +51,8 @@ const StripeCardForm = ({
t,
onDonationStateChange,
postStripeCardDonation,
processing
processing,
isAVariant
}: FormPropTypes): JSX.Element => {
const [isSubmissionValid, setSubmissionValidity] = useState(true);
const [isTokenizing, setTokenizing] = useState(false);
@ -167,7 +170,8 @@ const StripeCardForm = ({
disabled={!stripe || !elements || isSubmitting}
type='submit'
>
Donate
{isAVariant === false && <SecurityLockIcon />}
{t('buttons.donate')}
</Button>
</Form>
);

View File

@ -8,7 +8,6 @@ import {
take
} from 'redux-saga/effects';
import i18next from 'i18next';
import { fireConfetti } from '../utils/fire-confetti';
import {
addDonation,
@ -28,8 +27,7 @@ import {
postChargeStripeComplete,
postChargeStripeError,
postChargeStripeCardComplete,
postChargeStripeCardError,
isAVariantSelector
postChargeStripeCardError
} from './';
const defaultDonationErrorMessage = i18next.t('donate.error-2');
@ -40,12 +38,6 @@ function* showDonateModalSaga() {
yield delay(200);
const recentlyClaimedBlock = yield select(recentlyClaimedBlockSelector);
yield put(openDonationModal());
if (recentlyClaimedBlock) {
const isAVariant = yield select(isAVariantSelector);
if (isAVariant === false) {
fireConfetti();
}
}
yield take(appTypes.closeDonationModal);
if (recentlyClaimedBlock) {
yield put(preventBlockDonationRequests());

View File

@ -1,48 +0,0 @@
import confetti from 'canvas-confetti';
export const fireConfetti = () => {
const count = 200;
const defaults = {
origin: { y: 0.7 },
zIndex: 10000
};
function fire(
particleRatio: number,
opts: {
spread?: number;
startVelocity?: number;
decay?: number;
scalar?: number;
}
) {
confetti(
Object.assign({}, defaults, opts, {
particleCount: Math.floor(count * particleRatio)
})
)?.catch(err => console.log(err));
}
fire(0.25, {
spread: 26,
startVelocity: 55
});
fire(0.2, {
spread: 60
});
fire(0.35, {
spread: 100,
decay: 0.91,
scalar: 0.8
});
fire(0.1, {
spread: 120,
startVelocity: 25,
decay: 0.92,
scalar: 1.2
});
fire(0.1, {
spread: 120,
startVelocity: 45
});
};

View File

@ -94,7 +94,7 @@ const patreonDefaultPledgeAmount = 500;
const aBTestConfig = {
isTesting: true,
type: 'badgeProgressModalCopy'
type: 'addSecurityLock'
};
module.exports = {

28
package-lock.json generated
View File

@ -985,7 +985,6 @@
"@reach/router": "1.3.4",
"@stripe/react-stripe-js": "1.7.0",
"@stripe/stripe-js": "1.25.0",
"@types/canvas-confetti": "1.4.2",
"@types/react-scrollable-anchor": "0.6.1",
"algoliasearch": "4.13.0",
"assert": "2.0.0",
@ -994,7 +993,6 @@
"bezier-easing": "2.1.0",
"browser-cookies": "1.2.0",
"buffer": "6.0.3",
"canvas-confetti": "1.5.1",
"chai": "4.3.6",
"crypto-browserify": "3.12.0",
"date-fns": "2.27.0",
@ -15173,11 +15171,6 @@
"@types/responselike": "*"
}
},
"node_modules/@types/canvas-confetti": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.4.2.tgz",
"integrity": "sha512-t45KUDHlwrD9PJVRHc5z1SlXhO82BQEgMKUXGEV1KnWLFMPA6Y5LfUsLTHHzH9KcKDHZLEiYYH5nIDcjRKWNTg=="
},
"node_modules/@types/chai": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
@ -20421,15 +20414,6 @@
"resolved": "https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.4.tgz",
"integrity": "sha1-ZXnAcsPbXEd+xB3JePvyuPQQdKM="
},
"node_modules/canvas-confetti": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.5.1.tgz",
"integrity": "sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==",
"funding": {
"type": "donate",
"url": "https://www.paypal.me/kirilvatev"
}
},
"node_modules/capture-exit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
@ -56530,7 +56514,6 @@
"@stripe/stripe-js": "1.25.0",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.4",
"@types/canvas-confetti": "1.4.2",
"@types/react-scrollable-anchor": "0.6.1",
"algoliasearch": "4.13.0",
"assert": "2.0.0",
@ -56541,7 +56524,6 @@
"bezier-easing": "2.1.0",
"browser-cookies": "1.2.0",
"buffer": "6.0.3",
"canvas-confetti": "1.5.1",
"chai": "4.3.6",
"chokidar": "3.5.3",
"copy-webpack-plugin": "9.1.0",
@ -65612,11 +65594,6 @@
"@types/responselike": "*"
}
},
"@types/canvas-confetti": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.4.2.tgz",
"integrity": "sha512-t45KUDHlwrD9PJVRHc5z1SlXhO82BQEgMKUXGEV1KnWLFMPA6Y5LfUsLTHHzH9KcKDHZLEiYYH5nIDcjRKWNTg=="
},
"@types/chai": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz",
@ -70080,11 +70057,6 @@
"resolved": "https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.4.tgz",
"integrity": "sha1-ZXnAcsPbXEd+xB3JePvyuPQQdKM="
},
"canvas-confetti": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.5.1.tgz",
"integrity": "sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg=="
},
"capture-exit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",