mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
feat(console): sign in experience setup others tab (#662)
This commit is contained in:
parent
c5b1fed805
commit
875a31ec2a
6 changed files with 113 additions and 20 deletions
|
@ -0,0 +1,74 @@
|
||||||
|
import { Language } from '@logto/phrases';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import { Controller, useFormContext } from 'react-hook-form';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import FormField from '@/components/FormField';
|
||||||
|
import RadioGroup, { Radio } from '@/components/RadioGroup';
|
||||||
|
import Select from '@/components/Select';
|
||||||
|
|
||||||
|
import { LanguageMode, SignInExperienceForm } from '../types';
|
||||||
|
import * as styles from './index.module.scss';
|
||||||
|
|
||||||
|
const LanguagesForm = () => {
|
||||||
|
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
const { watch, control } = useFormContext<SignInExperienceForm>();
|
||||||
|
const mode = watch('languageInfo.mode');
|
||||||
|
|
||||||
|
const languageOptions = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
value: Language.English,
|
||||||
|
title: t('sign_in_exp.others.languages.languages.english'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: Language.Chinese,
|
||||||
|
title: t('sign_in_exp.others.languages.languages.chinese'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.title}>{t('sign_in_exp.others.languages.title')}</div>
|
||||||
|
<FormField isRequired title="admin_console.sign_in_exp.others.languages.mode">
|
||||||
|
<Controller
|
||||||
|
name="languageInfo.mode"
|
||||||
|
control={control}
|
||||||
|
defaultValue={LanguageMode.Auto}
|
||||||
|
render={({ field: { onChange, value, name } }) => (
|
||||||
|
<RadioGroup value={value} name={name} onChange={onChange}>
|
||||||
|
<Radio value={LanguageMode.Auto} title="sign_in_exp.others.languages.auto" />
|
||||||
|
<Radio value={LanguageMode.Fixed} title="sign_in_exp.others.languages.fixed" />
|
||||||
|
</RadioGroup>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
{mode === LanguageMode.Auto && (
|
||||||
|
<FormField isRequired title="admin_console.sign_in_exp.others.languages.fallback_language">
|
||||||
|
<Controller
|
||||||
|
name="languageInfo.fallbackLanguage"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange } }) => (
|
||||||
|
<Select value={value} options={languageOptions} onChange={onChange} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
)}
|
||||||
|
{mode === LanguageMode.Fixed && (
|
||||||
|
<FormField isRequired title="admin_console.sign_in_exp.others.languages.fixed_language">
|
||||||
|
<Controller
|
||||||
|
name="languageInfo.fixedLanguage"
|
||||||
|
control={control}
|
||||||
|
render={({ field: { value, onChange } }) => (
|
||||||
|
<Select value={value} options={languageOptions} onChange={onChange} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguagesForm;
|
|
@ -14,6 +14,7 @@ import useApi, { RequestError } from '@/hooks/use-api';
|
||||||
import * as detailsStyles from '@/scss/details.module.scss';
|
import * as detailsStyles from '@/scss/details.module.scss';
|
||||||
|
|
||||||
import BrandingForm from './components/BrandingForm';
|
import BrandingForm from './components/BrandingForm';
|
||||||
|
import LanguagesForm from './components/LanguagesForm';
|
||||||
import SignInMethodsForm from './components/SignInMethodsForm';
|
import SignInMethodsForm from './components/SignInMethodsForm';
|
||||||
import TermsForm from './components/TermsForm';
|
import TermsForm from './components/TermsForm';
|
||||||
import * as styles from './index.module.scss';
|
import * as styles from './index.module.scss';
|
||||||
|
@ -44,10 +45,8 @@ const SignInExperience = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedData = await api
|
const updatedData = await api
|
||||||
.patch(`/api/applications/${data.id}`, {
|
.patch('/api/sign-in-exp', {
|
||||||
json: {
|
json: signInExperienceParser.toRemoteModel(formData),
|
||||||
...formData,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.json<SignInExperienceType>();
|
.json<SignInExperienceType>();
|
||||||
void mutate(updatedData);
|
void mutate(updatedData);
|
||||||
|
@ -82,6 +81,7 @@ const SignInExperience = () => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{tab === 'methods' && <SignInMethodsForm />}
|
{tab === 'methods' && <SignInMethodsForm />}
|
||||||
|
{tab === 'others' && <LanguagesForm />}
|
||||||
<div className={detailsStyles.footer}>
|
<div className={detailsStyles.footer}>
|
||||||
<Button
|
<Button
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
|
import { Language } from '@logto/phrases';
|
||||||
import { SignInExperience, SignInMethods } from '@logto/schemas';
|
import { SignInExperience, SignInMethods } from '@logto/schemas';
|
||||||
|
|
||||||
export type SignInExperienceForm = Omit<SignInExperience, 'signInMethods'> & {
|
export enum LanguageMode {
|
||||||
|
Auto = 'Auto',
|
||||||
|
Fixed = 'Fixed',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SignInExperienceForm = Omit<SignInExperience, 'signInMethods' | 'languageInfo'> & {
|
||||||
signInMethods: {
|
signInMethods: {
|
||||||
primary?: keyof SignInMethods;
|
primary?: keyof SignInMethods;
|
||||||
enableSecondary: boolean;
|
enableSecondary: boolean;
|
||||||
|
@ -9,4 +15,9 @@ export type SignInExperienceForm = Omit<SignInExperience, 'signInMethods'> & {
|
||||||
email: boolean;
|
email: boolean;
|
||||||
social: boolean;
|
social: boolean;
|
||||||
};
|
};
|
||||||
|
languageInfo: {
|
||||||
|
mode: LanguageMode;
|
||||||
|
fixedLanguage: Language;
|
||||||
|
fallbackLanguage: Language;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
SignInMethodState,
|
SignInMethodState,
|
||||||
} from '@logto/schemas';
|
} from '@logto/schemas';
|
||||||
|
|
||||||
import { SignInExperienceForm } from './types';
|
import { LanguageMode, SignInExperienceForm } from './types';
|
||||||
|
|
||||||
const findMethodState = (
|
const findMethodState = (
|
||||||
setup: SignInExperienceForm,
|
setup: SignInExperienceForm,
|
||||||
|
@ -34,6 +34,10 @@ export const signInExperienceParser = {
|
||||||
(key) => signInExperience.signInMethods[key] === SignInMethodState.Secondary
|
(key) => signInExperience.signInMethods[key] === SignInMethodState.Secondary
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
languageInfo: { autoDetect, fallbackLanguage, fixedLanguage },
|
||||||
|
} = signInExperience;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...signInExperience,
|
...signInExperience,
|
||||||
signInMethods: {
|
signInMethods: {
|
||||||
|
@ -44,9 +48,18 @@ export const signInExperienceParser = {
|
||||||
email: secondaryMethods.includes(SignInMethodKey.Email),
|
email: secondaryMethods.includes(SignInMethodKey.Email),
|
||||||
social: secondaryMethods.includes(SignInMethodKey.Social),
|
social: secondaryMethods.includes(SignInMethodKey.Social),
|
||||||
},
|
},
|
||||||
|
languageInfo: {
|
||||||
|
mode: autoDetect ? LanguageMode.Auto : LanguageMode.Fixed,
|
||||||
|
fallbackLanguage,
|
||||||
|
fixedLanguage,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
toRemoteModel: (setup: SignInExperienceForm): SignInExperience => {
|
toRemoteModel: (setup: SignInExperienceForm): SignInExperience => {
|
||||||
|
const {
|
||||||
|
languageInfo: { mode, fallbackLanguage, fixedLanguage },
|
||||||
|
} = setup;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...setup,
|
...setup,
|
||||||
signInMethods: {
|
signInMethods: {
|
||||||
|
@ -55,6 +68,11 @@ export const signInExperienceParser = {
|
||||||
email: findMethodState(setup, 'email'),
|
email: findMethodState(setup, 'email'),
|
||||||
social: findMethodState(setup, 'social'),
|
social: findMethodState(setup, 'social'),
|
||||||
},
|
},
|
||||||
|
languageInfo: {
|
||||||
|
autoDetect: mode === LanguageMode.Auto,
|
||||||
|
fallbackLanguage,
|
||||||
|
fixedLanguage,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -388,18 +388,13 @@ const translation = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
others: {
|
others: {
|
||||||
forgot_password: {
|
|
||||||
title: 'FORGOT PASSWORD',
|
|
||||||
enable: 'Enable forgot password',
|
|
||||||
enable_description:
|
|
||||||
'Once it’s turned on, you app will support more sign in method(s) besides the primary one. ',
|
|
||||||
},
|
|
||||||
languages: {
|
languages: {
|
||||||
title: 'LANGUAGES',
|
title: 'LANGUAGES',
|
||||||
mode: 'Language mode',
|
mode: 'Language mode',
|
||||||
auto: 'Auto',
|
auto: 'Auto',
|
||||||
fixed: 'Fixed',
|
fixed: 'Fixed',
|
||||||
fallback: 'Fallback languages',
|
fallback_language: 'Fallback language',
|
||||||
|
fixed_language: 'Fixed language',
|
||||||
languages: {
|
languages: {
|
||||||
english: 'English',
|
english: 'English',
|
||||||
chinese: 'Chinese',
|
chinese: 'Chinese',
|
||||||
|
|
|
@ -384,18 +384,13 @@ const translation = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
others: {
|
others: {
|
||||||
forgot_password: {
|
|
||||||
title: 'FORGOT PASSWORD',
|
|
||||||
enable: 'Enable forgot password',
|
|
||||||
enable_description:
|
|
||||||
'Once it’s turned on, you app will support more sign in method(s) besides the primary one. ',
|
|
||||||
},
|
|
||||||
languages: {
|
languages: {
|
||||||
title: 'LANGUAGES',
|
title: 'LANGUAGES',
|
||||||
mode: 'Language mode',
|
mode: 'Language mode',
|
||||||
auto: 'Auto',
|
auto: 'Auto',
|
||||||
fixed: 'Fixed',
|
fixed: 'Fixed',
|
||||||
fallback: 'Fallback languages',
|
fallback_language: 'Fallback language',
|
||||||
|
fixed_language: 'Fixed language',
|
||||||
languages: {
|
languages: {
|
||||||
english: 'English',
|
english: 'English',
|
||||||
chinese: 'Chinese',
|
chinese: 'Chinese',
|
||||||
|
|
Loading…
Add table
Reference in a new issue