From 07b82b1d87eebbe1f2153208b5deb88a942b9649 Mon Sep 17 00:00:00 2001 From: Adeel Ehsan Date: Fri, 4 Jun 2021 20:13:12 +0500 Subject: [PATCH] Account activation pop up added: (#425) VAN-435 --- .env | 1 + .env.development | 1 + .../AccountActivationAlert.jsx | 135 ++++++++++++++++++ src/course-home/outline-tab/OutlineTab.jsx | 2 + .../outline-tab/OutlineTab.test.jsx | 48 +++++++ src/courseware/data/api.js | 5 + src/courseware/data/index.js | 1 + 7 files changed, 193 insertions(+) create mode 100644 src/alerts/logistration-alert/AccountActivationAlert.jsx diff --git a/.env b/.env index 2b2bf477..7619bc6b 100644 --- a/.env +++ b/.env @@ -32,3 +32,4 @@ TERMS_OF_SERVICE_URL='' TWITTER_HASHTAG='' TWITTER_URL='' USER_INFO_COOKIE_NAME='' +SESSION_COOKIE_DOMAIN='' \ No newline at end of file diff --git a/.env.development b/.env.development index f0b2b655..cf763714 100644 --- a/.env.development +++ b/.env.development @@ -32,3 +32,4 @@ TERMS_OF_SERVICE_URL='https://www.edx.org/edx-terms-service' TWITTER_HASHTAG='myedxjourney' TWITTER_URL='https://twitter.com/edXOnline' USER_INFO_COOKIE_NAME='edx-user-info' +SESSION_COOKIE_DOMAIN='localhost' \ No newline at end of file diff --git a/src/alerts/logistration-alert/AccountActivationAlert.jsx b/src/alerts/logistration-alert/AccountActivationAlert.jsx new file mode 100644 index 00000000..effc43b6 --- /dev/null +++ b/src/alerts/logistration-alert/AccountActivationAlert.jsx @@ -0,0 +1,135 @@ +import React, { useState } from 'react'; +import Cookies from 'js-cookie'; +import { getConfig } from '@edx/frontend-platform'; +import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; +import { + AlertModal, + Button, + Spinner, + Icon, +} from '@edx/paragon'; +import { Check, ArrowForward } from '@edx/paragon/icons'; +import { FormattedMessage, injectIntl } from '@edx/frontend-platform/i18n'; +import { sendActivationEmail } from '../../courseware/data'; + +function AccountActivationAlert() { + const [showModal, setShowModal] = useState(false); + const [showSpinner, setShowSpinner] = useState(false); + const [showCheck, setShowCheck] = useState(false); + const handleOnClick = () => { + setShowSpinner(true); + setShowCheck(false); + sendActivationEmail().then(() => { + setShowSpinner(false); + setShowCheck(true); + }); + }; + + const showAccountActivationAlert = Cookies.get('show-account-activation-popup'); + if (showAccountActivationAlert !== undefined) { + Cookies.remove('show-account-activation-popup', { path: '/', domain: process.env.SESSION_COOKIE_DOMAIN }); + // extra check to make sure cookie was removed before updating the state. Updating the state without removal + // of cookie would make it infinit rendering + if (Cookies.get('show-account-activation-popup') === undefined) { + setShowModal(true); + } + } + + const title = ( +

+ +

+ ); + + const button = ( + + ); + + const children = () => { + let bodyContent = null; + const message = ( + {getAuthenticatedUser().email}, + sendEmailTag: ( + // eslint-disable-next-line jsx-a11y/anchor-is-valid + + + + ), + }} + /> + ); + bodyContent = ( +
+ {message} +
+ ); + + if (!showCheck && showSpinner) { + bodyContent = ( +
+ {message} + +
+ ); + } + + if (showCheck && !showSpinner) { + bodyContent = ( +
+ {message} + +
+ ); + } + return bodyContent; + }; + + return ( + ({})} + > + {children()} + + ); +} + +export default injectIntl(AccountActivationAlert); diff --git a/src/course-home/outline-tab/OutlineTab.jsx b/src/course-home/outline-tab/OutlineTab.jsx index ac6eaa7a..15da2938 100644 --- a/src/course-home/outline-tab/OutlineTab.jsx +++ b/src/course-home/outline-tab/OutlineTab.jsx @@ -26,6 +26,7 @@ import usePrivateCourseAlert from './alerts/private-course-alert'; import { useModel } from '../../generic/model-store'; import WelcomeMessage from './widgets/WelcomeMessage'; import ProctoringInfoPanel from './widgets/ProctoringInfoPanel'; +import AccountActivationAlert from '../../alerts/logistration-alert/AccountActivationAlert'; /** [MM-P2P] Experiment */ import { initHomeMMP2P, MMP2PFlyover } from '../../experiments/mm-p2p'; @@ -131,6 +132,7 @@ function OutlineTab({ intl }) { {/** [MM-P2P] Experiment (className for optimizely trigger) */}
+
{ }); }); }); + + describe('Accont Activation Alert', () => { + beforeEach(() => { + const intersectionObserverMock = () => ({ + observe: () => null, + disconnect: () => null, + }); + window.IntersectionObserver = jest.fn().mockImplementation(intersectionObserverMock); + }); + it('displays account activation alert if cookie is set true', async () => { + Cookies.set = jest.fn(); + Cookies.get = jest.fn().mockImplementation(() => 'true'); + Cookies.remove = jest.fn().mockImplementation(() => { Cookies.get = jest.fn(); }); + + await fetchAndRender(); + expect(screen.queryByText('Activate your account so you can log back in')).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'resend the email' })).toBeInTheDocument(); + }); + + it('do not displays account activation alert if cookie is not set true', async () => { + Cookies.set = jest.fn(); + Cookies.get = jest.fn(); + Cookies.remove = jest.fn().mockImplementation(() => { Cookies.get = jest.fn(); }); + + await fetchAndRender(); + expect(screen.queryByText('Activate your account so you can log back in')).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'resend the email' })).not.toBeInTheDocument(); + }); + + it('sends account activation email on clicking the resened email in account activation alert', async () => { + Cookies.set = jest.fn(); + Cookies.get = jest.fn().mockImplementation(() => 'true'); + Cookies.remove = jest.fn().mockImplementation(() => { Cookies.get = jest.fn(); }); + + await fetchAndRender(); + + axiosMock = new MockAdapter(getAuthenticatedHttpClient()); + const resendEmailUrl = `${getConfig().LMS_BASE_URL}/api/send_account_activation_email`; + axiosMock.onPost(resendEmailUrl).reply(200, {}); + + const resendLink = screen.getByRole('button', { name: 'resend the email' }); + fireEvent.click(resendLink); + + await waitFor(() => expect(axiosMock.history.post).toHaveLength(1)); + expect(axiosMock.history.post[0].url).toEqual(resendEmailUrl); + }); + }); }); diff --git a/src/courseware/data/api.js b/src/courseware/data/api.js index c0670620..c66b0ec3 100644 --- a/src/courseware/data/api.js +++ b/src/courseware/data/api.js @@ -239,3 +239,8 @@ export async function postIntegritySignature(courseId) { ); return camelCaseObject(data); } +export async function sendActivationEmail() { + const url = new URL(`${getConfig().LMS_BASE_URL}/api/send_account_activation_email`); + const { data } = await getAuthenticatedHttpClient().post(url.href, {}); + return data; +} diff --git a/src/courseware/data/index.js b/src/courseware/data/index.js index 5961756d..72fe2bc4 100644 --- a/src/courseware/data/index.js +++ b/src/courseware/data/index.js @@ -7,6 +7,7 @@ export { } from './thunks'; export { getResumeBlock, + sendActivationEmail, } from './api'; export { sequenceIdsSelector,