diff --git a/packages/account/src/Components/sent-email-modal/sent-email-modal.tsx b/packages/account/src/Components/sent-email-modal/sent-email-modal.tsx index be40c8d518f4..cb271eaeb1e5 100644 --- a/packages/account/src/Components/sent-email-modal/sent-email-modal.tsx +++ b/packages/account/src/Components/sent-email-modal/sent-email-modal.tsx @@ -1,7 +1,7 @@ import { ReactElement } from 'react'; import { Localize, useTranslations, localize } from '@deriv-com/translations'; import { Div100vhContainer, Icon, MobileDialog, Modal, SendEmailTemplate, Text, Popover } from '@deriv/components'; -import { getPlatformSettings, CFD_PLATFORMS } from '@deriv/shared'; +import { getPlatformSettings, CFD_PLATFORMS, routes } from '@deriv/shared'; import { useDevice } from '@deriv-com/ui'; import { Chat } from '@deriv/utils'; @@ -151,15 +151,21 @@ const SentEmailModal = ({ ); } + const should_show_close_icon = + identifier_title !== 'Change_Email' || + (window.location.pathname === routes.passwords && identifier_title === 'Change_Email'); + identifier_title !== 'Change_Email'; + return ( -
- -
+ {should_show_close_icon && ( +
+ +
+ )} {sent_email_template}
diff --git a/packages/account/src/Sections/Security/Passwords/__tests__/passwords.spec.tsx b/packages/account/src/Sections/Security/Passwords/__tests__/passwords.spec.tsx index 4c57ccaa1a08..9381dfa130c9 100644 --- a/packages/account/src/Sections/Security/Passwords/__tests__/passwords.spec.tsx +++ b/packages/account/src/Sections/Security/Passwords/__tests__/passwords.spec.tsx @@ -43,24 +43,4 @@ describe('', () => { expect(screen.getByText('Email address')).toBeInTheDocument(); expect(screen.getByText('BrandDerivLogoCoralIcon')).toBeInTheDocument(); }); - - it('should render MT5 platform section', async () => { - const store_config = mockStore({ - client: { is_dxtrade_password_not_set: true }, - }); - renderComponent({ store_config }); - - const ele_mt5 = await screen.findAllByText('Deriv MT5 password'); - expect(ele_mt5).toHaveLength(2); - }); - - it('should render DerivX platform section', async () => { - const store_config = mockStore({ - client: { is_mt5_password_not_set: true }, - }); - renderComponent({ store_config }); - - const ele_derivx = await screen.findAllByText('Deriv X password'); - expect(ele_derivx).toHaveLength(2); - }); }); diff --git a/packages/account/src/Sections/Security/Passwords/passwords.tsx b/packages/account/src/Sections/Security/Passwords/passwords.tsx index 18ac11472ce4..b8c65198f165 100644 --- a/packages/account/src/Sections/Security/Passwords/passwords.tsx +++ b/packages/account/src/Sections/Security/Passwords/passwords.tsx @@ -3,8 +3,6 @@ import { Loading } from '@deriv/components'; import { observer, useStore } from '@deriv/stores'; import DerivPassword from './deriv-password'; import DerivEmail from './deriv-email'; -import DerivMt5Password from './deriv-mt5-password'; -import DerivXPassword from './deriv-x-password'; /** * Displays the Email, Password, section under Account settings. @@ -12,21 +10,10 @@ import DerivXPassword from './deriv-x-password'; * @returns {ReactNode} */ const Passwords = observer(() => { - const { client, common } = useStore(); - const { - is_populating_mt5_account_list, - is_populating_dxtrade_account_list, - is_social_signup, - mt5_login_list, - is_mt5_password_not_set, - dxtrade_accounts_list, - is_dxtrade_password_not_set, - } = client; - const { is_from_derivgo } = common; + const { client } = useStore(); + const { is_populating_mt5_account_list, is_populating_dxtrade_account_list, is_social_signup } = client; const [is_loading, setIsLoading] = useState(true); - const has_mt5_accounts = mt5_login_list?.length > 0 || !is_mt5_password_not_set; - const has_dxtrade_accounts = dxtrade_accounts_list?.length > 0 || !is_dxtrade_password_not_set; useEffect(() => { if ( @@ -46,8 +33,6 @@ const Passwords = observer(() => {
- {!is_from_derivgo && has_mt5_accounts && } - {!is_from_derivgo && has_dxtrade_accounts && }
); }); diff --git a/packages/core/src/App/Constants/routes-config.js b/packages/core/src/App/Constants/routes-config.js index 68307c3e2be7..7fe9ad7ca8a2 100644 --- a/packages/core/src/App/Constants/routes-config.js +++ b/packages/core/src/App/Constants/routes-config.js @@ -8,6 +8,7 @@ import { localize } from '@deriv/translations'; import Redirect from 'App/Containers/Redirect'; import RootComponent from 'App/Containers/RootComponent'; import Endpoint from 'Modules/Endpoint'; +import RedirectionPage from 'Modules/redirection-page'; import OSRedirect from '../Containers/OSRedirect'; import CallbackPage from '../../Modules/Callback/CallbackPage.tsx'; @@ -383,6 +384,7 @@ const initRoutesConfig = () => [ { path: routes.index, component: RouterRedirect, getTitle: () => '', to: routes.traders_hub }, { path: routes.endpoint, component: Endpoint, getTitle: () => 'Endpoint' }, // doesn't need localization as it's for internal use { path: routes.os_redirect, component: OSRedirect, getTitle: () => localize('Redirect') }, + { path: routes.redirect_page, component: RedirectionPage, getTitle: () => '' }, { path: routes.redirect, component: Redirect, getTitle: () => localize('Redirect') }, { path: routes.callback_page, component: CallbackPage, getTitle: () => 'Callback' }, { diff --git a/packages/core/src/App/Containers/Layout/app-contents.jsx b/packages/core/src/App/Containers/Layout/app-contents.jsx index 94c6e37da29f..21236df57be8 100644 --- a/packages/core/src/App/Containers/Layout/app-contents.jsx +++ b/packages/core/src/App/Containers/Layout/app-contents.jsx @@ -125,7 +125,8 @@ const AppContents = observer(({ children }) => { 'app-contents--is-route-modal': is_route_modal_on, 'app-contents--is-scrollable': is_cfd_page || is_cashier_visible, 'app-contents--is-hidden': platforms[platform] && !(is_from_tradershub_os && isMobile), - 'app-contents--is-onboarding': window.location.pathname === routes.onboarding, + 'app-contents--is-onboarding': + window.location.pathname === routes.onboarding || window.location.pathname === routes.redirect_page, 'app-contents--is-dtrader-v2': dtrader_v2_enabled_mobile || dtrader_v2_enabled_desktop, })} ref={scroll_ref} diff --git a/packages/core/src/App/Containers/Layout/footer.jsx b/packages/core/src/App/Containers/Layout/footer.jsx index d7901a7e1c4d..896349f980ab 100644 --- a/packages/core/src/App/Containers/Layout/footer.jsx +++ b/packages/core/src/App/Containers/Layout/footer.jsx @@ -12,7 +12,7 @@ const Footer = () => { const is_dtrader_route = pathname === routes.trade; const show_in_tablet_routes = [routes.contract]; - if (pathname === routes.onboarding) { + if (pathname === routes.onboarding || pathname === routes.redirect_page) { return null; } diff --git a/packages/core/src/App/Containers/Layout/header/header.tsx b/packages/core/src/App/Containers/Layout/header/header.tsx index 40cb7edc1608..e7317a9c3034 100644 --- a/packages/core/src/App/Containers/Layout/header/header.tsx +++ b/packages/core/src/App/Containers/Layout/header/header.tsx @@ -76,6 +76,7 @@ const Header = observer(() => { let result; switch (true) { case pathname === routes.onboarding: + case pathname === routes.redirect_page: result = null; break; case traders_hub_routes: @@ -93,7 +94,7 @@ const Header = observer(() => { break; } return result; - } else if (pathname === routes.onboarding) { + } else if (pathname === routes.onboarding || pathname === routes.redirect_page) { return null; } return has_wallet ? : ; diff --git a/packages/core/src/App/Containers/LinkExpiredModal/__tests__/link-expired-modal.spec.tsx b/packages/core/src/App/Containers/LinkExpiredModal/__tests__/link-expired-modal.spec.tsx index fafec9cf56c1..bc079cdfa430 100644 --- a/packages/core/src/App/Containers/LinkExpiredModal/__tests__/link-expired-modal.spec.tsx +++ b/packages/core/src/App/Containers/LinkExpiredModal/__tests__/link-expired-modal.spec.tsx @@ -42,7 +42,7 @@ describe('LinkExpiredModal', () => { expect(screen.queryByText('Link expired')).not.toBeInTheDocument(); }); - it('should not render the component close and resend email buttons', () => { + it('should render the component resend email buttons', () => { // @ts-expect-error ignore this until find a way to make arguments as partial mockUseRequest.mockReturnValue({ isLoading: false }); const mock = mockStore({ ui: { is_link_expired_modal_visible: true } }); @@ -53,7 +53,7 @@ describe('LinkExpiredModal', () => { ), }); - expect(screen.getByRole('button', { name: /Close/ })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Resend email/ })).toBeInTheDocument(); }); @@ -76,24 +76,7 @@ describe('LinkExpiredModal', () => { expect(resend_button).toBeEnabled(); }); - it('should close the modal on clicking close button', async () => { - // @ts-expect-error ignore this until find a way to make arguments as partial - mockUseRequest.mockReturnValue({ isLoading: false }); - const mock = mockStore({ ui: { is_link_expired_modal_visible: true } }); - render(, { - wrapper: ({ children }) => ( - - {children} - - ), - }); - const close_button = screen.getByRole('button', { name: /Close/ }); - userEvent.click(close_button); - expect(mock.ui.toggleLinkExpiredModal).toBeCalledTimes(1); - expect(mock.ui.toggleLinkExpiredModal).toHaveBeenCalledWith(false); - }); - - it('should call the verify email websocket API on clicking resend mail button', () => { + it('should call the verify email websocket API on clicking resend mail button', async () => { // @ts-expect-error ignore this until find a way to make arguments as partial mockUseRequest.mockReturnValue({ isLoading: false }); const mock = mockStore({ ui: { is_link_expired_modal_visible: true } }); @@ -108,7 +91,7 @@ describe('LinkExpiredModal', () => { fireEvent.change(screen.getByRole('textbox', { name: /Email address/i }), { target: { value: 'test.mail@domain.com' }, }); - userEvent.click(resend_button); + await userEvent.click(resend_button); expect(mockUseRequest).toBeCalledWith('verify_email'); }); }); diff --git a/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx b/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx index 8ba00217b65e..596fbdb71ddd 100644 --- a/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx +++ b/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx @@ -59,7 +59,6 @@ const LinkExpiredModal = observer(() => { disableApp={disableApp} enableApp={enableApp} title={is_email_sent ? '' : localize('Link expired')} - has_close_icon onConfirm={() => toggleLinkExpiredModal(false)} >
@@ -92,9 +91,6 @@ const LinkExpiredModal = observer(() => { /> toggleLinkExpiredModal(false)} is_disabled={!values.email || !!errors.email || isSubmitting} is_loading={isSubmitting} label={localize('Resend email')} diff --git a/packages/core/src/App/Containers/Redirect/redirect.jsx b/packages/core/src/App/Containers/Redirect/redirect.jsx index b0a8886f4a49..4d6dafc57073 100644 --- a/packages/core/src/App/Containers/Redirect/redirect.jsx +++ b/packages/core/src/App/Containers/Redirect/redirect.jsx @@ -93,6 +93,12 @@ const Redirect = observer(() => { break; } case 'reset_password': { + history.push({ + pathname: routes.redirect_page, + search: url_query_string, + }); + redirected_to_route = true; + toggleResetPasswordModal(true); break; } @@ -104,6 +110,11 @@ const Redirect = observer(() => { redirectToLogin(is_logged_in, getLanguage(), true); redirected_to_route = true; } else { + history.push({ + pathname: routes.redirect_page, + search: url_query_string, + }); + redirected_to_route = true; if (!verification_code[action_param]) { const request_email_code = sessionStorage.getItem('request_email_code'); setVerificationCode(request_email_code, action_param); @@ -114,10 +125,20 @@ const Redirect = observer(() => { break; } case 'social_email_change': { + history.push({ + pathname: routes.redirect_page, + search: url_query_string, + }); + redirected_to_route = true; toggleResetPasswordModal(true); break; } case 'system_email_change': { + history.push({ + pathname: routes.redirect_page, + search: url_query_string, + }); + redirected_to_route = true; toggleUpdateEmailModal(true); break; } diff --git a/packages/core/src/App/Containers/ResetEmailModal/reset-email-modal.tsx b/packages/core/src/App/Containers/ResetEmailModal/reset-email-modal.tsx index d7974cecca9c..800ef2b5aef1 100644 --- a/packages/core/src/App/Containers/ResetEmailModal/reset-email-modal.tsx +++ b/packages/core/src/App/Containers/ResetEmailModal/reset-email-modal.tsx @@ -1,9 +1,10 @@ import React from 'react'; import classNames from 'classnames'; import { Formik, Form, FormikErrors } from 'formik'; +import { useHistory } from 'react-router-dom'; import { Button, Dialog, Text, Input } from '@deriv/components'; -import { validEmail, getErrorMessages } from '@deriv/shared'; -import { Localize, localize } from '@deriv/translations'; +import { validEmail, getErrorMessages, loginUrl, routes } from '@deriv/shared'; +import { Localize, localize, getLanguage } from '@deriv/translations'; import { ConfirmEmailModal } from '../ConfirmEmailModal/confirm-email-modal'; import { observer, useStore } from '@deriv/stores'; @@ -13,8 +14,9 @@ type TResetEmailInitValues = { const ResetEmailModal = observer(() => { const { ui, client } = useStore(); + const history = useHistory(); const { disableApp, enableApp, is_loading, is_reset_email_modal_visible: is_visible, toggleResetEmailModal } = ui; - const { email } = client; + const { email, is_logged_in } = client; const [is_confirm_email_modal_open, setIsConfirmResetEmailModal] = React.useState(false); const [email_error_msg, setEmailErrorMsg] = React.useState(''); const [email_value, setEmailValue] = React.useState(''); @@ -50,7 +52,14 @@ const ResetEmailModal = observer(() => { /> ); } - + const onCancel = () => { + toggleResetEmailModal(false); + if (is_logged_in) { + history.push(routes.passwords); + } else { + window.location.href = loginUrl({ language: getLanguage() }); + } + }; return ( { dismissable={status.error_msg || email_error_msg} onConfirm={() => toggleResetEmailModal(false)} is_closed_on_cancel={false} + has_close_icon={!!errors.email || !!email_error_msg} + onClose={onCancel} >
diff --git a/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx b/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx index 13d52bbfbe3f..965f724031f5 100644 --- a/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx +++ b/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx @@ -2,7 +2,7 @@ import React from 'react'; import classNames from 'classnames'; import { Formik, Form, FormikHelpers, FormikErrors } from 'formik'; import { Button, Dialog, PasswordInput, PasswordMeter, Text } from '@deriv/components'; -import { redirectToLogin, validPassword, validLength, getErrorMessages, WS, removeActionParam } from '@deriv/shared'; +import { validPassword, validLength, getErrorMessages, WS, removeActionParam, loginUrl } from '@deriv/shared'; import { getLanguage, localize, Localize } from '@deriv/translations'; import { observer, useStore } from '@deriv/stores'; import { TSocketError, TSocketRequest, TSocketResponse } from '@deriv/api/types'; @@ -49,7 +49,9 @@ const ResetPasswordModal = observer(() => { actions.setStatus({ reset_complete: true }); logoutClient().then(() => { - redirectToLogin(false, getLanguage(), false); + sessionStorage.removeItem('redirect_url'); + removeActionParam('reset_password'); + window.location.href = loginUrl({ language: getLanguage() }); }); }; @@ -114,7 +116,6 @@ const ResetPasswordModal = observer(() => { dismissable={status.error_msg} onConfirm={closeResetPasswordModal} title={localize('Reset your password')} - has_close_icon is_closed_on_cancel={false} >
diff --git a/packages/core/src/App/Containers/UpdateEmailModal/update-email-modal.jsx b/packages/core/src/App/Containers/UpdateEmailModal/update-email-modal.jsx index ee3550ffd904..dbcefe3ade7b 100644 --- a/packages/core/src/App/Containers/UpdateEmailModal/update-email-modal.jsx +++ b/packages/core/src/App/Containers/UpdateEmailModal/update-email-modal.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, Modal, Text, Icon, Loading } from '@deriv/components'; import { localize, Localize, getLanguage } from '@deriv/translations'; -import { redirectToLogin, removeActionParam } from '@deriv/shared'; +import { loginUrl, removeActionParam } from '@deriv/shared'; import { WS } from 'Services'; import { observer, useStore } from '@deriv/stores'; @@ -15,15 +15,20 @@ const UpdateEmailModal = observer(() => { const [is_email_updated, setIsEmailUpdated] = React.useState(false); const [update_email_error, setUpdateEmailMessage] = React.useState(null); + const redirectToLogout = () => { + window.location.href = loginUrl({ language: getLanguage() }); + }; + const onClickButton = () => { - toggleUpdateEmailModal(false); + sessionStorage.removeItem('redirect_url'); removeActionParam('system_email_change'); + toggleUpdateEmailModal(false); if (is_logged_in) { logoutClient().then(() => { - redirectToLogin(false, getLanguage(), false); + redirectToLogout(); }); } else { - redirectToLogin(false, getLanguage(), false); + redirectToLogout(); } }; @@ -61,6 +66,7 @@ const UpdateEmailModal = observer(() => { toggleModal={toggleUpdateEmailModal} width='440px' minHeight='400px' + should_close_on_click_outside={false} > {is_email_updated ? (
diff --git a/packages/core/src/Modules/redirection-page/index.ts b/packages/core/src/Modules/redirection-page/index.ts new file mode 100644 index 000000000000..0a493a144efe --- /dev/null +++ b/packages/core/src/Modules/redirection-page/index.ts @@ -0,0 +1,5 @@ +import RedirectionPage from './redirection-page'; + +import './redirection-page.scss'; + +export default RedirectionPage; diff --git a/packages/core/src/Modules/redirection-page/redirection-page.scss b/packages/core/src/Modules/redirection-page/redirection-page.scss new file mode 100644 index 000000000000..7bfbf2fccca0 --- /dev/null +++ b/packages/core/src/Modules/redirection-page/redirection-page.scss @@ -0,0 +1,10 @@ +.redirection_page { + width: 100%; + height: 100%; + &__logo { + display: flex; + justify-content: center; + align-items: center; + height: 7.2rem; + } +} diff --git a/packages/core/src/Modules/redirection-page/redirection-page.tsx b/packages/core/src/Modules/redirection-page/redirection-page.tsx new file mode 100644 index 000000000000..c684eb559863 --- /dev/null +++ b/packages/core/src/Modules/redirection-page/redirection-page.tsx @@ -0,0 +1,13 @@ +import { BrandBrandLightDerivWordmarkHorizontal25YearsEnglishIcon } from '@deriv/quill-icons'; + +import './redirection-page.scss'; + +const RedirectionPage = () => ( +
+
+ +
+
+); + +export default RedirectionPage; diff --git a/packages/shared/src/utils/routes/routes.ts b/packages/shared/src/utils/routes/routes.ts index b59948790390..cdce52992b4e 100644 --- a/packages/shared/src/utils/routes/routes.ts +++ b/packages/shared/src/utils/routes/routes.ts @@ -84,6 +84,7 @@ export const routes = { traders_hub: '/', onboarding: '/onboarding', compare_cfds: '/cfd-compare-accounts', + redirect_page: '/redirect-page', // Wallets wallets: '/wallet', @@ -102,6 +103,7 @@ export const routes = { export const DISABLE_LANDSCAPE_BLOCKER_ROUTES = [ routes.trade, routes.onboarding, + routes.redirect_page, routes.compare_cfds, routes.reports, routes.bot,