0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-24 22:05:56 -05:00

refactor(console): use Translation type from @logto/schemas (#2006)

This commit is contained in:
Xiao Yijun 2022-09-27 12:27:59 +08:00 committed by GitHub
parent 58e1f9f0da
commit 505985802b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 60 deletions

View file

@ -1,5 +1,5 @@
import type { Translation as UiTranslation } from '@logto/phrases-ui'; import { Translation } from '@logto/schemas';
import { FieldPath, useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import TextInput from '@/components/TextInput'; import TextInput from '@/components/TextInput';
@ -7,11 +7,11 @@ import * as style from './EditSection.module.scss';
type EditSectionProps = { type EditSectionProps = {
dataKey: string; dataKey: string;
data: Record<string, unknown>; data: Record<string, string>;
}; };
const EditSection = ({ dataKey, data }: EditSectionProps) => { const EditSection = ({ dataKey, data }: EditSectionProps) => {
const { register } = useFormContext<UiTranslation>(); const { register } = useFormContext<Translation>();
return ( return (
<> <>
@ -21,10 +21,6 @@ const EditSection = ({ dataKey, data }: EditSectionProps) => {
</td> </td>
</tr> </tr>
{Object.entries(data).map(([field, value]) => { {Object.entries(data).map(([field, value]) => {
if (typeof value !== 'string') {
return null;
}
const fieldKey = `${dataKey}.${field}`; const fieldKey = `${dataKey}.${field}`;
return ( return (
@ -34,10 +30,7 @@ const EditSection = ({ dataKey, data }: EditSectionProps) => {
<TextInput readOnly value={value} className={style.sectionBuiltInText} /> <TextInput readOnly value={value} className={style.sectionBuiltInText} />
</td> </td>
<td> <td>
{ <TextInput {...register(fieldKey)} />
// eslint-disable-next-line no-restricted-syntax
<TextInput {...register(fieldKey as FieldPath<UiTranslation>)} />
}
</td> </td>
</tr> </tr>
); );

View file

@ -1,8 +1,6 @@
import type { LanguageKey } from '@logto/core-kit'; import type { LanguageKey } from '@logto/core-kit';
import resource, { import resource, { languageCodeAndDisplayNameMappings } from '@logto/phrases-ui';
languageCodeAndDisplayNameMappings, import { Translation } from '@logto/schemas';
Translation as UiTranslation,
} from '@logto/phrases-ui';
import cleanDeep from 'clean-deep'; import cleanDeep from 'clean-deep';
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
@ -14,7 +12,7 @@ import Button from '@/components/Button';
import useApi, { RequestError } from '@/hooks/use-api'; import useApi, { RequestError } from '@/hooks/use-api';
import Delete from '@/icons/Delete'; import Delete from '@/icons/Delete';
import { createEmptyUiTranslation, flattenObject } from '../../utilities'; import { createEmptyUiTranslation, flattenTranslation } from '../../utilities';
import EditSection from './EditSection'; import EditSection from './EditSection';
import * as style from './LanguageEditor.module.scss'; import * as style from './LanguageEditor.module.scss';
import { CustomPhraseResponse } from './types'; import { CustomPhraseResponse } from './types';
@ -50,7 +48,7 @@ const LanguageEditor = ({ selectedLanguageKey, onFormStateChange }: LanguageEdit
} }
); );
const formMethods = useForm<UiTranslation>(); const formMethods = useForm<Translation>();
const { const {
handleSubmit, handleSubmit,
@ -62,7 +60,7 @@ const LanguageEditor = ({ selectedLanguageKey, onFormStateChange }: LanguageEdit
onFormStateChange(isDirty); onFormStateChange(isDirty);
}, [isDirty, onFormStateChange]); }, [isDirty, onFormStateChange]);
const onSubmit = handleSubmit(async (formData: UiTranslation) => { const onSubmit = handleSubmit(async (formData: Translation) => {
const updatedCustomPhrase = await api const updatedCustomPhrase = await api
.put(`/api/custom-phrases/${selectedLanguageKey}`, { .put(`/api/custom-phrases/${selectedLanguageKey}`, {
json: { json: {
@ -123,7 +121,7 @@ const LanguageEditor = ({ selectedLanguageKey, onFormStateChange }: LanguageEdit
<tbody> <tbody>
<FormProvider {...formMethods}> <FormProvider {...formMethods}>
{translationEntries.map(([key, value]) => ( {translationEntries.map(([key, value]) => (
<EditSection key={key} dataKey={key} data={flattenObject(value)} /> <EditSection key={key} dataKey={key} data={flattenTranslation(value)} />
))} ))}
</FormProvider> </FormProvider>
</tbody> </tbody>

View file

@ -1,7 +1,7 @@
import type { LanguageKey } from '@logto/core-kit'; import type { LanguageKey } from '@logto/core-kit';
import type { Translation as UiTranslation } from '@logto/phrases-ui'; import type { Translation } from '@logto/schemas';
export type CustomPhraseResponse = { export type CustomPhraseResponse = {
languageKey: LanguageKey; languageKey: LanguageKey;
translation: UiTranslation; translation: Translation;
}; };

View file

@ -1,4 +1,3 @@
import type { Translation as UiTranslation } from '@logto/phrases-ui';
import en from '@logto/phrases-ui/lib/locales/en'; import en from '@logto/phrases-ui/lib/locales/en';
import { import {
SignInExperience, SignInExperience,
@ -6,6 +5,7 @@ import {
SignInMethods, SignInMethods,
SignInMethodState, SignInMethodState,
SignInMode, SignInMode,
Translation,
} from '@logto/schemas'; } from '@logto/schemas';
import { conditional } from '@silverhand/essentials'; import { conditional } from '@silverhand/essentials';
@ -101,47 +101,33 @@ export const compareSignInMethods = (
return Object.values(SignInMethodKey).every((key) => beforeMethods[key] === afterMethods[key]); return Object.values(SignInMethodKey).every((key) => beforeMethods[key] === afterMethods[key]);
}; };
// TODO: LOG-4235 move this method into @silverhand/essentials export const flattenTranslation = (
const isObject = (data: unknown): data is Record<string, unknown> => translation: Translation,
typeof data === 'object' && !Array.isArray(data);
export const flattenObject = (
object: Record<string, unknown>,
keyPrefix = '' keyPrefix = ''
): Record<string, unknown> => { ): Record<string, string> =>
return Object.keys(object).reduce((result, key) => { Object.keys(translation).reduce((result, key) => {
const prefix = keyPrefix ? `${keyPrefix}.` : keyPrefix; const prefix = keyPrefix ? `${keyPrefix}.` : keyPrefix;
const dataKey = `${prefix}${key}`; const unwrappedKey = `${prefix}${key}`;
const data = object[key]; const unwrapped = translation[key];
return { return unwrapped
? {
...result, ...result,
...(isObject(data) ? flattenObject(data, dataKey) : { [dataKey]: data }), ...(typeof unwrapped === 'string'
}; ? { [unwrappedKey]: unwrapped }
: flattenTranslation(unwrapped, unwrappedKey)),
}
: result;
}, {}); }, {});
};
const emptyTranslation = (translation: Record<string, unknown>): Record<string, unknown> => { const emptyTranslation = (translation: Translation): Translation =>
return Object.entries(translation).reduce<Record<string, unknown>>((result, [key, value]) => { Object.entries(translation).reduce((result, [key, value]) => {
if (isObject(value)) { return typeof value === 'string'
return { ? { ...result, [key]: '' }
: {
...result, ...result,
[key]: emptyTranslation(value), [key]: emptyTranslation(value),
}; };
}
if (typeof value === 'string') {
return {
...result,
[key]: '',
};
}
return { ...result, [key]: value };
}, {}); }, {});
};
export const createEmptyUiTranslation = () => { export const createEmptyUiTranslation = () => emptyTranslation(en.translation);
// eslint-disable-next-line no-restricted-syntax
return emptyTranslation(en.translation) as UiTranslation;
};