Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CA-4467] Permettre aux marques de surcharger le callback onSuccess et onError sur les widgets #251

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ export type ProviderId = typeof providerKeys[number]
* The widget’s initial screen.
* @enum {('login' | 'login-with-web-authn' | 'signup' | 'forgot-password')}
*/
export type InitialScreen = 'login' | 'login-with-web-authn' | 'signup' | 'forgot-password'
export type InitialScreen = 'login' | 'login-with-web-authn' | 'signup' | 'signup-with-password' | 'signup-with-web-authn' | 'forgot-password'
4 changes: 1 addition & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/components/form/passwordSignupFormComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ export interface PasswordSignupFormProps {
showLabels?: boolean
signupFields?: (string | Field)[]
userAgreement?: string
/**
* Callback function called when the request has succeed.
*/
onSuccess?: () => void
/**
* Callback function called when the request has failed.
*/
onError?: (error?: unknown) => void
}

export const PasswordSignupForm = ({
Expand All @@ -54,6 +62,8 @@ export const PasswordSignupForm = ({
'password_confirmation'
],
userAgreement,
onError = () => {},
onSuccess = () => {},
}: PasswordSignupFormProps) => {
const coreClient = useReachfive()
const config = useConfig()
Expand Down Expand Up @@ -121,6 +131,8 @@ export const PasswordSignupForm = ({
...phoneNumberOptions,
}}
handler={(data: SignupParams['data']) => ReCaptcha.handle(data, { recaptcha_enabled, recaptcha_site_key }, callback, "signup")}
onSuccess={onSuccess}
onError={onError}
/>
}

Expand Down
20 changes: 14 additions & 6 deletions src/components/form/socialButtonsComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,23 +121,31 @@ export interface SocialButtonsProps {
* List of authentication options
*/
auth?: AuthOptions
/**
* Classname
*/
className?: string
/**
* Lists the available social providers. This is an array of strings.
*
* Tip: If you pass an empty array, social providers will not be displayed.
* */
providers: string[]
/**
* Callback function called when the request has succeed.
*/
onSuccess?: () => void
/**
* Callback function called when the request has failed.
*/
onError?: (error?: unknown) => void
}

export const SocialButtons = styled(({ auth, providers, className }: SocialButtonsProps) => {
export const SocialButtons = styled(({ auth, providers, className, onError = () => {}, onSuccess = () => {} }: SocialButtonsProps & { className?: string }) => {
const coreClient = useReachfive()

const clickHandler = useCallback(
(provider: string) => coreClient.loginWithSocialProvider(provider, auth),
(provider: string) => {
coreClient.loginWithSocialProvider(provider, auth)
.then(() => onSuccess())
.catch(onError)
},
[coreClient, auth],
)

Expand Down
6 changes: 4 additions & 2 deletions src/components/form/webAuthAndPasswordButtonsComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ export const WebAuthnSignupViewButtons = styled(({ enablePasswordAuthentication,
data-testid="webauthn-button"
onClick={onBiometricClick}
title={i18n('signup.withBiometrics')}
text={i18n('biometrics')}>
text={i18n('biometrics')}
>
<FingerPrintIcon />
</PrimaryButtonWithIcon>

Expand All @@ -129,7 +130,8 @@ export const WebAuthnSignupViewButtons = styled(({ enablePasswordAuthentication,
data-testid="password-button"
onClick={onPasswordClick}
title={i18n('signup.withPassword')}
text={i18n('password')}>
text={i18n('password')}
>
<KeyboardIcon />
</PrimaryButtonWithIcon>
</>
Expand Down
4 changes: 2 additions & 2 deletions src/components/widget/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { StyleSheetManager, ThemeProvider } from 'styled-components'
import type { SessionInfo, Client as CoreClient } from '@reachfive/identity-core'

import type { Config, Prettify } from '../../types'
import type { I18nMessages } from '../../core/i18n';
import type { I18nMessages, I18nNestedMessages } from '../../core/i18n';

import { ConfigProvider } from '../../contexts/config';
import { I18nProvider } from '../../contexts/i18n'
Expand All @@ -16,7 +16,7 @@ import { buildTheme } from '../../core/theme'

import WidgetContainer, { WidgetContainerProps } from './widgetContainerComponent';

export type I18nProps = { i18n?: I18nMessages }
export type I18nProps = { i18n?: I18nNestedMessages }
export type ThemeProps = { theme?: ThemeOptions }

export type PropsWithI18n<P> = Prettify<P & I18nProps>
Expand Down
50 changes: 25 additions & 25 deletions src/widgets/accountRecovery/accountRecoveryWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ interface MainViewProps {
*/
allowCreatePassword?: boolean
/**
* Callback function called when the request has failed.
* Callback function called when the request has succeed.
*/
onSuccess?: () => void
/**
* Callback function called after the widget has been successfully loaded and rendered inside the container.
* The callback is called with the widget instance.
* Callback function called when the request has failed.
*/
onError?: () => void
onError?: (error?: unknown) => void
/**
* Whether the form fields' labels are displayed on the form view.
* @default false
Expand Down Expand Up @@ -57,26 +56,26 @@ const PasskeysIcon = styled(Passkeys)`${iconStyle}`;
const PasskeysExplanation = styled(() => {
const i18n = useI18n()
return (
<ul>
<li><b>{i18n('accountRecovery.passkeyReset.subtitle1')}</b></li>
<ul>
<li>{i18n('accountRecovery.passkeyReset.legend1')}</li>
</ul>
<li><b>{i18n('accountRecovery.passkeyReset.subtitle2')}</b></li>
<ul>
<li><b>{i18n('accountRecovery.passkeyReset.subtitle1')}</b></li>
<ul>
<li>{i18n('accountRecovery.passkeyReset.legend1')}</li>
</ul>
<li><b>{i18n('accountRecovery.passkeyReset.subtitle2')}</b></li>
<ul>
<li>{i18n('accountRecovery.passkeyReset.legend2')}</li>
</ul>
<li>{i18n('accountRecovery.passkeyReset.legend2')}</li>
</ul>
</ul>
)
})`
`;

const NewPasskey = ({
authentication,
allowCreatePassword = true,
onSuccess = () => {},
onError = () => {},
}: PropsWithAuthentication<MainViewProps>) => {
authentication,
allowCreatePassword = true,
onSuccess = () => {},
onError = () => {},
}: PropsWithAuthentication<MainViewProps>) => {
const coreClient = useReachfive()
const i18n = useI18n()
const {goTo} = useRouting()
Expand Down Expand Up @@ -108,7 +107,7 @@ const NewPasskey = ({
{allowCreatePassword &&
<Alternative>
<Separator text={i18n('or')} />
<Intro><Link target="new-password">Create a new password</Link></Intro>
<Intro><Link target="new-password">{i18n('accountRecovery.password.title')}</Link></Intro>
</Alternative>
}
</div>
Expand Down Expand Up @@ -150,11 +149,11 @@ const PasswordSuccessView = ({loginLink}: SuccessViewProps) => {
}

export const NewPasswordView = ({
authentication,
onSuccess = () => {},
onError = () => {},
showLabels = false,
}: PropsWithAuthentication<MainViewProps>) => {
authentication,
onSuccess = () => {},
onError = () => {},
showLabels = false,
}: PropsWithAuthentication<MainViewProps>) => {
const coreClient = useReachfive()
const i18n = useI18n()
const { goTo } = useRouting()
Expand All @@ -179,9 +178,10 @@ export const NewPasswordView = ({
handler={handleSubmit}
showLabels={showLabels}
onSuccess={handleSuccess}
onError={onError} />
onError={onError}
/>
<Alternative>
<Link target="new-passkey">Back</Link>
<Link target="new-passkey">{i18n('back')}</Link>
</Alternative>
</div>
)
Expand Down
19 changes: 17 additions & 2 deletions src/widgets/auth/views/accountRecoveryViewComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ export interface AccountRecoveryViewProps {
* Important: This parameter should only be used with Hosted Pages.
*/
returnToAfterAccountRecovery?: string,
/**
* Callback function called when the request has succeed.
*/
onSuccess?: () => void
/**
* Callback function called when the request has failed.
*/
onError?: (error?: unknown) => void
}

export const AccountRecoveryView = ({
Expand All @@ -78,6 +86,8 @@ export const AccountRecoveryView = ({
recaptcha_site_key,
redirectUrl,
returnToAfterAccountRecovery,
onError = () => {},
onSuccess = () => {},
}: AccountRecoveryViewProps) => {
const coreClient = useReachfive()
const { goTo } = useRouting()
Expand All @@ -104,8 +114,13 @@ export const AccountRecoveryView = ({
<AccountRecoveryForm
showLabels={showLabels}
handler={callback}
onSuccess={() => goTo('account-recovery-success')}
skipError={displaySafeErrorMessage && skipError} />
onSuccess={() => {
onSuccess()
goTo('account-recovery-success')
}}
onError={onError}
skipError={displaySafeErrorMessage && skipError}
/>
{allowLogin && <Alternative>
<Link target={'login'}>{i18n('accountRecovery.backToLoginLink')}</Link>
</Alternative>}
Expand Down
30 changes: 25 additions & 5 deletions src/widgets/auth/views/forgotPasswordViewComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ export interface ForgotPasswordViewProps {
* Important: This parameter should only be used with Hosted Pages.
*/
returnToAfterPasswordReset?: string,
/**
* Callback function called when the request has succeed.
*/
onSuccess?: () => void
/**
* Callback function called when the request has failed.
*/
onError?: (error?: unknown) => void
}

export const ForgotPasswordView = ({
Expand All @@ -172,6 +180,8 @@ export const ForgotPasswordView = ({
recaptcha_site_key,
redirectUrl,
returnToAfterPasswordReset,
onError = () => {},
onSuccess = () => {},
}: ForgotPasswordViewProps) => {
const coreClient = useReachfive()
const config = useConfig()
Expand All @@ -190,8 +200,6 @@ export const ForgotPasswordView = ({
[coreClient, recaptcha_enabled, recaptcha_site_key, redirectUrl, returnToAfterPasswordReset]
)

const onSuccess = () => goTo('forgot-password-success')

useLayoutEffect(() => {
importGoogleRecaptchaScript(recaptcha_site_key)
}, [recaptcha_site_key])
Expand All @@ -203,7 +211,11 @@ export const ForgotPasswordView = ({
<ForgotPasswordEmailForm
showLabels={showLabels}
handler={callback}
onSuccess={onSuccess}
onSuccess={() => {
onSuccess()
goTo('forgot-password-success')
}}
onError={onError}
skipError={displaySafeErrorMessage && skipError}
/>
{allowPhoneNumberResetPassword && config.sms && (
Expand Down Expand Up @@ -231,6 +243,7 @@ export const ForgotPasswordPhoneNumberView = ({
recaptcha_site_key,
redirectUrl,
returnToAfterPasswordReset,
onError = () => {},
}: ForgotPasswordViewProps) => {
const coreClient = useReachfive()
const { goTo } = useRouting()
Expand Down Expand Up @@ -265,6 +278,7 @@ export const ForgotPasswordPhoneNumberView = ({
showLabels={showLabels}
handler={callback}
onSuccess={onSuccess}
onError={onError}
skipError={displaySafeErrorMessage && skipError}
phoneNumberOptions={phoneNumberOptions}
/>
Expand All @@ -285,7 +299,9 @@ export const ForgotPasswordCodeView = ({
displaySafeErrorMessage = false,
initialScreen,
allowWebAuthnLogin = false,
showLabels = false
showLabels = false,
onError = () => {},
onSuccess = () => {},
}: ForgotPasswordViewProps) => {
const coreClient = useReachfive()
const { goTo, params } = useRouting()
Expand All @@ -308,7 +324,11 @@ export const ForgotPasswordCodeView = ({
<VerificationCodeForm
showLabels={showLabels}
handler={callback}
onSuccess={() => goTo('login')}
onSuccess={() => {
onSuccess()
goTo('login')
}}
onError={onError}
skipError={displaySafeErrorMessage && skipError}
/>
{allowLogin && (
Expand Down
Loading