mirror of
https://github.com/logto-io/logto.git
synced 2025-04-14 23:11:31 -05:00
refactor(console): extract manage language components (#2088)
This commit is contained in:
parent
c21cc3cab6
commit
c9ef62479d
17 changed files with 68 additions and 51 deletions
|
@ -1,7 +1,6 @@
|
|||
import { languages as uiLanguageNameMapping } from '@logto/language-kit';
|
||||
import { SignInExperience } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useSWR from 'swr';
|
||||
|
@ -9,13 +8,11 @@ import useSWR from 'swr';
|
|||
import FormField from '@/components/FormField';
|
||||
import Select from '@/components/Select';
|
||||
import Switch from '@/components/Switch';
|
||||
import * as textButtonStyles from '@/components/TextButton/index.module.scss';
|
||||
import { RequestError } from '@/hooks/use-api';
|
||||
import useUiLanguages from '@/hooks/use-ui-languages';
|
||||
|
||||
import useLanguageEditorContext from '../hooks/use-language-editor-context';
|
||||
import { SignInExperienceForm } from '../types';
|
||||
import ManageLanguageModal from './ManageLanguageModal';
|
||||
import ManageLanguageButton from './ManageLanguage/ManageLanguageButton';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
|
@ -28,7 +25,6 @@ const LanguagesForm = ({ isManageLanguageVisible = false }: Props) => {
|
|||
const { watch, control, register, setValue } = useFormContext<SignInExperienceForm>();
|
||||
const isAutoDetect = watch('languageInfo.autoDetect');
|
||||
const selectedDefaultLanguage = watch('languageInfo.fallbackLanguage');
|
||||
const [isManageLanguageFormOpen, setIsManageLanguageFormOpen] = useState(false);
|
||||
const { languages } = useUiLanguages();
|
||||
|
||||
const languageOptions = useMemo(() => {
|
||||
|
@ -38,9 +34,6 @@ const LanguagesForm = ({ isManageLanguageVisible = false }: Props) => {
|
|||
}));
|
||||
}, [languages]);
|
||||
|
||||
const { context: languageEditorContext, Provider: LanguageEditorContextProvider } =
|
||||
useLanguageEditorContext(languages);
|
||||
|
||||
useEffect(() => {
|
||||
if (!languages.includes(selectedDefaultLanguage)) {
|
||||
setValue(
|
||||
|
@ -58,19 +51,8 @@ const LanguagesForm = ({ isManageLanguageVisible = false }: Props) => {
|
|||
{...register('languageInfo.autoDetect')}
|
||||
label={t('sign_in_exp.others.languages.description')}
|
||||
/>
|
||||
{isManageLanguageVisible && <ManageLanguageButton />}
|
||||
</FormField>
|
||||
{isManageLanguageVisible && (
|
||||
// TODO: @yijun
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
||||
<div
|
||||
className={classNames(textButtonStyles.button, styles.manageLanguage)}
|
||||
onClick={() => {
|
||||
setIsManageLanguageFormOpen(true);
|
||||
}}
|
||||
>
|
||||
{t('sign_in_exp.others.languages.manage_language')}
|
||||
</div>
|
||||
)}
|
||||
<FormField title="sign_in_exp.others.languages.default_language">
|
||||
<Controller
|
||||
name="languageInfo.fallbackLanguage"
|
||||
|
@ -85,15 +67,6 @@ const LanguagesForm = ({ isManageLanguageVisible = false }: Props) => {
|
|||
: t('sign_in_exp.others.languages.default_language_description_fixed')}
|
||||
</div>
|
||||
</FormField>
|
||||
<LanguageEditorContextProvider value={languageEditorContext}>
|
||||
<ManageLanguageModal
|
||||
isOpen={isManageLanguageFormOpen}
|
||||
languageTags={languages}
|
||||
onClose={() => {
|
||||
setIsManageLanguageFormOpen(false);
|
||||
}}
|
||||
/>
|
||||
</LanguageEditorContextProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.languageEditor {
|
||||
.languageDetails {
|
||||
flex-grow: 1;
|
||||
|
||||
.title {
|
|
@ -17,14 +17,14 @@ import IconButton from '@/components/IconButton';
|
|||
import useApi, { RequestError } from '@/hooks/use-api';
|
||||
import { CustomPhraseResponse } from '@/types/custom-phrase';
|
||||
|
||||
import { LanguageEditorContext } from '../../hooks/use-language-editor-context';
|
||||
import { createEmptyUiTranslation, flattenTranslation } from '../../utilities';
|
||||
import { createEmptyUiTranslation, flattenTranslation } from '../../../utilities';
|
||||
import EditSection from './EditSection';
|
||||
import * as style from './LanguageEditor.module.scss';
|
||||
import * as style from './LanguageDetails.module.scss';
|
||||
import { LanguageEditorContext } from './use-language-editor-context';
|
||||
|
||||
const emptyUiTranslation = createEmptyUiTranslation();
|
||||
|
||||
const LanguageEditor = () => {
|
||||
const LanguageDetails = () => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const { data: signInExperience } = useSWR<SignInExperience, RequestError>('/api/sign-in-exp');
|
||||
|
@ -164,7 +164,7 @@ const LanguageEditor = () => {
|
|||
]);
|
||||
|
||||
return (
|
||||
<div className={style.languageEditor}>
|
||||
<div className={style.languageDetails}>
|
||||
<div className={style.title}>
|
||||
<div className={style.languageInfo}>
|
||||
{uiLanguageNameMapping[selectedLanguage]}
|
||||
|
@ -260,4 +260,4 @@ const LanguageEditor = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default LanguageEditor;
|
||||
export default LanguageDetails;
|
|
@ -5,10 +5,10 @@ import {
|
|||
} from '@logto/language-kit';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { LanguageEditorContext } from '../../hooks/use-language-editor-context';
|
||||
import AddLanguageSelector from './AddLanguageSelector';
|
||||
import LanguageItem from './LanguageItem';
|
||||
import * as style from './LanguageNav.module.scss';
|
||||
import { LanguageEditorContext } from './use-language-editor-context';
|
||||
|
||||
const LanguageNav = () => {
|
||||
const {
|
|
@ -1,27 +1,27 @@
|
|||
import { LanguageTag } from '@logto/language-kit';
|
||||
import { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import ConfirmModal from '@/components/ConfirmModal';
|
||||
import ModalLayout from '@/components/ModalLayout';
|
||||
import useUiLanguages from '@/hooks/use-ui-languages';
|
||||
import * as modalStyles from '@/scss/modal.module.scss';
|
||||
|
||||
import { LanguageEditorContext } from '../../hooks/use-language-editor-context';
|
||||
import LanguageEditor from './LanguageEditor';
|
||||
import LanguageDetails from './LanguageDetails';
|
||||
import LanguageNav from './LanguageNav';
|
||||
import * as style from './index.module.scss';
|
||||
import useLanguageEditorContext, { LanguageEditorContext } from './use-language-editor-context';
|
||||
|
||||
type ManageLanguageModalProps = {
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
languageTags: LanguageTag[];
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ManageLanguageModal = ({ isOpen, languageTags, onClose }: ManageLanguageModalProps) => {
|
||||
const LanguageEditorModal = ({ isOpen, onClose }: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const {
|
||||
languages,
|
||||
preSelectedLanguage,
|
||||
preAddedLanguage,
|
||||
isAddingLanguage,
|
||||
|
@ -42,7 +42,7 @@ const ManageLanguageModal = ({ isOpen, languageTags, onClose }: ManageLanguageMo
|
|||
}
|
||||
|
||||
onClose();
|
||||
setSelectedLanguage(languageTags[0] ?? 'en');
|
||||
setSelectedLanguage(languages[0] ?? 'en');
|
||||
};
|
||||
|
||||
const onConfirmUnsavedChanges = () => {
|
||||
|
@ -74,7 +74,7 @@ const ManageLanguageModal = ({ isOpen, languageTags, onClose }: ManageLanguageMo
|
|||
>
|
||||
<div className={style.container}>
|
||||
<LanguageNav />
|
||||
<LanguageEditor />
|
||||
<LanguageDetails />
|
||||
</div>
|
||||
</ModalLayout>
|
||||
<ConfirmModal
|
||||
|
@ -91,4 +91,16 @@ const ManageLanguageModal = ({ isOpen, languageTags, onClose }: ManageLanguageMo
|
|||
);
|
||||
};
|
||||
|
||||
export default ManageLanguageModal;
|
||||
const LanguageEditor = (props: Props) => {
|
||||
const { languages } = useUiLanguages();
|
||||
const { context: languageEditorContext, Provider: LanguageEditorContextProvider } =
|
||||
useLanguageEditorContext(languages);
|
||||
|
||||
return (
|
||||
<LanguageEditorContextProvider value={languageEditorContext}>
|
||||
<LanguageEditorModal {...props} />
|
||||
</LanguageEditorContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageEditor;
|
|
@ -0,0 +1,5 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.manageLanguage {
|
||||
margin-top: _.unit(2);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import { useState } from 'react';
|
||||
|
||||
import Button from '@/components/Button';
|
||||
|
||||
import LanguageEditor from './LanguageEditor';
|
||||
import * as styles from './ManageLanguageButton.module.scss';
|
||||
|
||||
const ManageLanguageButton = () => {
|
||||
const [isLanguageEditorOpen, setIsLanguageEditorOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
type="plain"
|
||||
title="sign_in_exp.others.languages.manage_language"
|
||||
className={styles.manageLanguage}
|
||||
onClick={() => {
|
||||
setIsLanguageEditorOpen(true);
|
||||
}}
|
||||
/>
|
||||
<LanguageEditor
|
||||
isOpen={isLanguageEditorOpen}
|
||||
onClose={() => {
|
||||
setIsLanguageEditorOpen(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ManageLanguageButton;
|
|
@ -29,10 +29,6 @@
|
|||
color: var(--color-caption);
|
||||
}
|
||||
|
||||
.manageLanguage {
|
||||
margin-top: _.unit(2);
|
||||
}
|
||||
|
||||
.defaultLanguageDescription {
|
||||
padding-top: _.unit(2);
|
||||
font: var(--font-body-medium);
|
||||
|
|
Loading…
Add table
Reference in a new issue