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:
parent
58e1f9f0da
commit
505985802b
4 changed files with 37 additions and 60 deletions
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
? {
|
||||||
...(isObject(data) ? flattenObject(data, dataKey) : { [dataKey]: data }),
|
...result,
|
||||||
};
|
...(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,
|
: {
|
||||||
[key]: emptyTranslation(value),
|
...result,
|
||||||
};
|
[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;
|
|
||||||
};
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue