Skip to content

Commit 69f5ccc

Browse files
author
MargeBot
committed
Merge branch 'born-private-complete' into 'main'
Born Private complete See merge request web/clients!23093
2 parents 93c74b8 + 0142eaf commit 69f5ccc

80 files changed

Lines changed: 3280 additions & 128 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

applications/account/src/app/content/PublicAppInteractive.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { replaceUrl } from '@proton/shared/lib/helpers/browser';
2121
import { FlagProvider } from '@proton/unleash/proxy';
2222
import noop from '@proton/utils/noop';
2323

24+
import bornPrivateActivatePage from '../../pages/born-private.activate';
25+
import bornPrivateRecoveryPage from '../../pages/born-private.recovery';
2426
import forgotUsernamePage from '../../pages/forgot-username';
2527
import resetPasswordPage from '../../pages/reset-password';
2628
import locales from '../locales';
@@ -51,6 +53,8 @@ import SignInWithAnotherDeviceContainer from '../public/signInWithAnotherDevice/
5153
import ResetPasswordContainer from '../reset/ResetPasswordContainer';
5254
import SignupInviteContainer from '../signup/SignupInviteContainer';
5355
import { getSignupMeta } from '../signup/signupPagesJson';
56+
import Activation from '../signupCtx/flows/bornPrivate/activation/Activation';
57+
import Recovery from '../signupCtx/flows/bornPrivate/recovery/Recovery';
5458
import SingleSignupContainer from '../single-signup/SingleSignupContainer';
5559
import { extraThunkArguments } from '../store/public-thunk';
5660
import type useLocationWithoutLocale from '../useLocationWithoutLocale';
@@ -392,6 +396,19 @@ const PublicAppInteractive = ({
392396
/>
393397
</UnAuthenticated>
394398
</Route>
399+
<Route path={SSO_PATHS.BORN_PRIVATE_ACTIVATE}>
400+
<UnAuthenticated>
401+
<Activation
402+
metaTags={bornPrivateActivatePage()}
403+
onLogin={handleLogin}
404+
/>
405+
</UnAuthenticated>
406+
</Route>
407+
<Route path={SSO_PATHS.BORN_PRIVATE_RECOVERY}>
408+
<UnAuthenticated>
409+
<Recovery metaTags={bornPrivateRecoveryPage()} />
410+
</UnAuthenticated>
411+
</Route>
395412
<Route
396413
path={[
397414
SSO_PATHS.SIGNUP,
@@ -414,8 +431,8 @@ const PublicAppInteractive = ({
414431
SSO_PATHS.MEET_SIGNUP_B2B,
415432
SSO_PATHS.PORKBUN_SIGNUP,
416433
SSO_PATHS.PORKBUN_SIGN_IN,
417-
SSO_PATHS.FIRST_EMAIL,
418434
SSO_PATHS.GREENLAND_SIGNUP,
435+
SSO_PATHS.BORN_PRIVATE,
419436
]}
420437
>
421438
<SingleSignupSwitchContainer

applications/account/src/app/content/SingleSignupSwitchContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const SingleSignupSwitchContainer = ({
5757
const renderContextSignup =
5858
searchParams.get('mode') === 'ctx' ||
5959
location.pathname === SSO_PATHS.START ||
60-
location.pathname === SSO_PATHS.FIRST_EMAIL ||
60+
location.pathname === SSO_PATHS.BORN_PRIVATE ||
6161
location.pathname === SSO_PATHS.MEET_SIGNUP ||
6262
location.pathname === SSO_PATHS.GREENLAND_SIGNUP ||
6363
isReferral;

applications/account/src/app/content/theme/getThemeFromLocation.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export const getThemeFromLocation = (
5151
location.pathname === SSO_PATHS.DOCS_SIGNUP ||
5252
location.pathname === SSO_PATHS.VPN_SIGNUP ||
5353
location.pathname === SSO_PATHS.LUMO_SIGNUP ||
54-
location.pathname === SSO_PATHS.MEET_SIGNUP
54+
location.pathname === SSO_PATHS.MEET_SIGNUP ||
55+
location.pathname.startsWith(SSO_PATHS.BORN_PRIVATE)
5556
) {
5657
return {
5758
LightTheme: ThemeTypes.Storefront,

applications/account/src/app/signupCtx/SignupCtxRouter.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ import { Redirect, Route, Switch } from 'react-router-dom';
22

33
import { PaymentsContextOptimisticProvider } from '@proton/payments/ui';
44
import { SSO_PATHS } from '@proton/shared/lib/constants';
5-
import { useFlag } from '@proton/unleash/useFlag';
65

76
import { cachedPlans } from '../defaultPlans';
87
import type { BaseSignupContextProps } from './context/SignupContext';
8+
import EmailReservationSignup from './flows/bornPrivate/emailReservation/EmailReservationSignup';
99
import DrivePricing from './flows/drive/DrivePricing';
1010
import DriveSignup from './flows/drive/DriveSignup';
11-
import FirstEmailReservationFlowSignup from './flows/firstEmailReservation/FirstEmailReservationFlow';
1211
import GenericStartSignup from './flows/genericStart/GenericStartSignup';
1312
import GreenlandSignup from './flows/greenland/GreenlandSignup';
1413
import MeetB2CSignup from './flows/meet/MeetB2CSignup';
@@ -45,9 +44,17 @@ const GenericSignupController = (props: BaseSignupContextProps) => {
4544
);
4645
};
4746

48-
const SignupCtxRouter = (props: BaseSignupContextProps) => {
49-
const firstEmailEnabled = useFlag('FirstEmail');
47+
const EmailReservationController = () => {
48+
return (
49+
<Switch>
50+
<Route>
51+
<EmailReservationSignup />
52+
</Route>
53+
</Switch>
54+
);
55+
};
5056

57+
const SignupCtxRouter = (props: BaseSignupContextProps) => {
5158
return (
5259
<PaymentsContextOptimisticProvider preload={false} authenticated={false} cachedPlans={cachedPlans}>
5360
<Switch>
@@ -63,19 +70,17 @@ const SignupCtxRouter = (props: BaseSignupContextProps) => {
6370
<Route path={SSO_PATHS.MEET_SIGNUP}>
6471
<MeetB2CSignup {...props} />
6572
</Route>
66-
{firstEmailEnabled && (
67-
<Route path={SSO_PATHS.FIRST_EMAIL}>
68-
<FirstEmailReservationFlowSignup {...props} />
69-
</Route>
70-
)}
7173
<Route path={SSO_PATHS.GREENLAND_SIGNUP}>
7274
<GreenlandSignup {...props} />
7375
</Route>
76+
<Route path={SSO_PATHS.BORN_PRIVATE}>
77+
<EmailReservationController />
78+
</Route>
7479
<Route>
7580
<GenericSignupController {...props} />
7681
</Route>
77-
</Switch>
78-
</PaymentsContextOptimisticProvider>
82+
</Switch >
83+
</PaymentsContextOptimisticProvider >
7984
);
8085
};
8186

applications/account/src/app/signupCtx/containers/username/useEmailInput.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ interface Props {
2323
emailReadOnly?: boolean;
2424
emailDisabled?: boolean;
2525
emailLabelHidden?: boolean;
26+
27+
usernameLabelHidden?: boolean;
28+
usernameLabel?: string;
2629
}
2730

2831
const useEmailInput = ({
@@ -34,6 +37,8 @@ const useEmailInput = ({
3437
emailLabelHidden,
3538
bigger,
3639
inputClassName,
40+
usernameLabelHidden,
41+
usernameLabel,
3742
}: Props) => {
3843
const anchorRef = useRef<HTMLButtonElement | null>(null);
3944
const accountDataContext = useAccountFormDataContext();
@@ -156,7 +161,7 @@ const useEmailInput = ({
156161
bigger={bigger}
157162
ref={refs.username}
158163
id="username"
159-
label={c('Signup label').t`Username`}
164+
label={usernameLabelHidden ? undefined : usernameLabel || c('Signup label').t`Username`}
160165
error={errors.username}
161166
inputClassName="email-input-field"
162167
suffix={(() => {

applications/account/src/app/signupCtx/context/accountData/AccountFormDataContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,8 @@ const getErrorAssistDetails = (
370370
const emailAssistError = getAssistVisible(inputStates.email) ? errorDetails.email : undefined;
371371
const emailAlreadyUsed = Boolean(
372372
emailAssistError &&
373-
asyncStates.email.error &&
374-
getApiError(asyncStates.email.error)?.code === API_CUSTOM_ERROR_CODES.ALREADY_USED
373+
asyncStates.email.error &&
374+
getApiError(asyncStates.email.error)?.code === API_CUSTOM_ERROR_CODES.ALREADY_USED
375375
);
376376

377377
return {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Redirect, useLocation } from 'react-router-dom';
2+
3+
import { CircleLoader } from '@proton/atoms/CircleLoader/CircleLoader';
4+
import type { OnLoginCallback } from '@proton/components/containers/app/interface';
5+
import { SSO_PATHS } from '@proton/shared/lib/constants';
6+
import { useFlagsStatus } from '@proton/unleash/proxy';
7+
import { useFlag } from '@proton/unleash/useFlag';
8+
9+
import { type MetaTags, useMetaTags } from '../../../../useMetaTags';
10+
import ActivationForm from './ActivationForm';
11+
import { decodeActivationParams } from './helpers/activationHelpers';
12+
13+
interface ActivationProps {
14+
onLogin: OnLoginCallback;
15+
metaTags: MetaTags;
16+
}
17+
18+
const Activation = ({ onLogin, metaTags }: ActivationProps) => {
19+
useMetaTags(metaTags);
20+
const location = useLocation();
21+
const { flagsReady } = useFlagsStatus();
22+
const isBornPrivateActivationRecoveryEnabled = useFlag('BornPrivateActivationRecovery');
23+
24+
if (!flagsReady) {
25+
return (
26+
<div className="flex items-center justify-center h-full w-full">
27+
<CircleLoader size="large" />
28+
</div>
29+
);
30+
}
31+
32+
if (!isBornPrivateActivationRecoveryEnabled) {
33+
return <Redirect to={SSO_PATHS.LOGIN} />;
34+
}
35+
36+
const prefilledParams = decodeActivationParams(location.hash);
37+
38+
return <ActivationForm prefilledParams={prefilledParams} onLogin={onLogin} />;
39+
};
40+
41+
export default Activation;

0 commit comments

Comments
 (0)