Skip to content

Commit

Permalink
Merge pull request #17630 from mozilla/FXA-7894
Browse files Browse the repository at this point in the history
feat(settings): Update AccountRecoveryConfirmKey to new design with hint
  • Loading branch information
vpomerleau authored Sep 23, 2024
2 parents 6e2d6d1 + b141e9b commit c90e1ab
Show file tree
Hide file tree
Showing 14 changed files with 664 additions and 187 deletions.
474 changes: 474 additions & 0 deletions apps/payments/next/lib/metrics/glean/server_events.ts

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/functional-tests/pages/resetPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,25 +94,25 @@ export class ResetPasswordPage extends BaseLayout {

get confirmRecoveryKeyHeading() {
return this.page.getByRole('heading', {
name: 'Reset password with account recovery key',
name: 'Enter your account recovery key',
});
}

get recoveryKeyTextbox() {
return this.page.getByRole('textbox', {
name: 'Enter account recovery key',
name: 'Enter your 32-character account recovery key',
});
}

get confirmRecoveryKeyButton() {
return this.page.getByRole('button', {
name: 'Confirm account recovery key',
name: 'Continue',
});
}

get forgotKeyLink() {
return this.page.getByRole('link', {
name: 'Don’t have an account recovery key?',
name: 'Can’t find your account recovery key?',
});
}

Expand Down
7 changes: 5 additions & 2 deletions packages/functional-tests/tests/settings/recoveryKey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,14 @@ test.describe('severity-1 #smoke', () => {

await settings.recoveryKey.createButton.click();
await recoveryKey.createRecoveryKey(credentials.password, HINT);
await expect(page.getByRole('alert')).toHaveText(
'Account recovery key created'
);

await expect(settings.settingsHeading).toBeVisible();
await expect(settings.recoveryKey.status).toHaveText('Enabled');

await settings.goto();
await expect(settings.recoveryKey.deleteButton).toBeVisible();
await expect(settings.recoveryKey.deleteButton).toBeEnabled();

await settings.recoveryKey.deleteButton.click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { isEmailValid } from 'fxa-shared/email/helpers';
export type LinkRememberPasswordProps = {
email?: string;
clickHandler?: () => void;
textStart?: boolean;
};

const LinkRememberPassword = ({
email,
clickHandler,
textStart,
}: LinkRememberPasswordProps) => {
let linkHref: string;
const location = useLocation();
Expand Down Expand Up @@ -44,7 +46,11 @@ const LinkRememberPassword = ({
};

return (
<div className="flex flex-wrap gap-2 justify-center text-sm mt-6">
<div
className={`flex flex-wrap gap-2 text-sm mt-6 ${
textStart ? 'text-start' : 'justify-center'
}`}
>
<FtlMsg id="remember-password-text">
<p>Remember your password?</p>
</FtlMsg>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const UnitRowRecoveryKey = () => {
const recoveryKey = account.recoveryKey.exists;
const alertBar = useAlertBar();
const [modalRevealed, revealModal, hideModal] = useBooleanState();
const [isLoading, setIsLoading] = useState<boolean>(false);
const [isDeleting, setIsDeleting] = useState<boolean>(false);
const ftlMsgResolver = useFtlMsgResolver();

const deleteRecoveryKey = useCallback(async () => {
Expand All @@ -44,7 +44,7 @@ export const UnitRowRecoveryKey = () => {
);
logViewEvent('flow.settings.account-recovery', 'confirm-revoke.fail');
} finally {
setIsLoading(false);
setIsDeleting(false);
}
}, [account, hideModal, alertBar, ftlMsgResolver]);

Expand Down Expand Up @@ -81,7 +81,7 @@ export const UnitRowRecoveryKey = () => {
<ButtonIconTrash
title={localizedDeleteRKIconButton}
classNames="inline-block mobileLandscape:hidden ms-1"
disabled={!recoveryKey || account.loading}
disabled={!recoveryKey || isDeleting}
onClick={revealModal}
/>
)
Expand All @@ -92,7 +92,7 @@ export const UnitRowRecoveryKey = () => {
<ButtonIconTrash
title={localizedDeleteRKIconButton}
classNames="hidden mobileLandscape:inline-block ms-1"
disabled={!recoveryKey || account.loading}
disabled={!recoveryKey || isDeleting}
onClick={revealModal}
/>
)
Expand Down Expand Up @@ -125,7 +125,7 @@ export const UnitRowRecoveryKey = () => {
hideModal();
}}
onConfirm={() => {
setIsLoading(true);
setIsDeleting(true);
deleteRecoveryKey();
logViewEvent(
'flow.settings.account-recovery',
Expand All @@ -136,7 +136,7 @@ export const UnitRowRecoveryKey = () => {
confirmText={ftlMsgResolver.getMsg('rk-action-remove', 'Remove')}
headerId="recovery-key-header"
descId="recovery-key-desc"
isLoading={isLoading}
isLoading={isDeleting}
>
<FtlMsg id="rk-remove-modal-heading-1">
<h2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,15 @@ import { decryptRecoveryKeyData } from 'fxa-auth-client/lib/recoveryKey';
import { useAccount, useSensitiveDataClient } from '../../../models';
import { useFtlMsgResolver } from '../../../models/hooks';

import {
AccountRecoveryConfirmKeyContainerProps,
AccountRecoveryConfirmKeyLocationState,
} from './interfaces';
import { AccountRecoveryConfirmKeyLocationState } from './interfaces';

import AccountRecoveryConfirmKey from '.';
import { useNavigateWithQuery } from '../../../lib/hooks/useNavigateWithQuery';
import { getLocalizedErrorMessage } from '../../../lib/error-utils';

const AccountRecoveryConfirmKeyContainer = ({
serviceName,
}: AccountRecoveryConfirmKeyContainerProps & RouteComponentProps) => {
const AccountRecoveryConfirmKeyContainer = (_: RouteComponentProps) => {
const [errorMessage, setErrorMessage] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitDisabled, setIsSubmitDisabled] = useState(true);
const account = useAccount();
const ftlMsgResolver = useFtlMsgResolver();
const location = useLocation();
Expand All @@ -37,6 +32,7 @@ const AccountRecoveryConfirmKeyContainer = ({
emailToHashWith,
estimatedSyncDeviceCount,
recoveryKeyExists,
recoveryKeyHint,
token,
uid,
} = (location.state as AccountRecoveryConfirmKeyLocationState) || {};
Expand Down Expand Up @@ -99,7 +95,7 @@ const AccountRecoveryConfirmKeyContainer = ({
ftlMsgResolver,
error
);
setIsSubmitting(false);
setIsSubmitDisabled(false);
setErrorMessage(localizedBannerMessage);
}
};
Expand All @@ -113,11 +109,11 @@ const AccountRecoveryConfirmKeyContainer = ({
emailToHashWith,
errorMessage,
estimatedSyncDeviceCount,
isSubmitting,
isSubmitDisabled,
recoveryKeyExists,
serviceName,
recoveryKeyHint,
setErrorMessage,
setIsSubmitting,
setIsSubmitDisabled,
token,
verifyRecoveryKey,
uid,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
## AccountRecoveryConfirmKey page

# Strings within the <span> elements appear as a subheading.
# If more appropriate in a locale, the string within the <span>, "to continue to account settings" can stand alone as "Continue to account settings"
account-recovery-confirm-key-heading-w-default-service = Reset password with account recovery key <span>to continue to account settings</span>
# Strings within the <span> elements appear as a subheading.
# If more appropriate in a locale, the string within the <span>, "to continue to { $serviceName }" can stand alone as "Continue to { $serviceName }"
# { $serviceName } represents a product name (e.g., Mozilla VPN) that will be passed in as a variable
account-recovery-confirm-key-heading-w-custom-service = Reset password with account recovery key <span>to continue to { $serviceName }</span>
account-recovery-confirm-key-heading = Enter your account recovery key
account-recovery-confirm-key-instructions-2 = Please enter the one time use account recovery key you stored in a safe place to regain access to your { -product-mozilla-account }.
account-recovery-confirm-key-instruction = This key recovers your encrypted browsing data, such as passwords and bookmarks, from { -brand-firefox } servers.
account-recovery-confirm-key-warning-message = <span>Note:</span> If you reset your password and don’t have your account recovery key saved, some of your data will be erased (including synced server data like history and bookmarks).
# Prompts the user to enter their account recovery code
account-recovery-confirm-key-input =
.label = Enter account recovery key
# Prompts the user to enter their account recovery key
# Account recovery key contains a mix of letters and numbers, no special characters
account-recovery-confirm-key-input-label =
.label = Enter your 32-character account recovery key
# When setting up an account recovery key, users have the option of storing an account recovery key hint that is shown during password reset
account-recovery-confirm-key-hint = Your storage hint is:
# Clicking this button checks if the recovery key provided by the user is correct and associated with their account
account-recovery-confirm-key-button = Confirm account recovery key
account-recovery-confirm-key-button-2 = Continue
# Link that leads to the password reset page (without recovery code)
account-recovery-lost-recovery-key-link = Don’t have an account recovery key?
account-recovery-lost-recovery-key-link-2 = Can’t find your account recovery key?
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ export default {
} as Meta;

export const Default = () => <Subject />;

export const WithError = () => <Subject success={false} />;

export const WithHint = () => (
<Subject recoveryKeyHint="My key is stored in Fort Knox" />
);
Loading

0 comments on commit c90e1ab

Please sign in to comment.