mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(console): add placeholders (#1277)
This commit is contained in:
parent
8dedd9dae1
commit
c26ca08fb1
11 changed files with 78 additions and 10 deletions
|
@ -18,9 +18,10 @@ type Props = {
|
|||
onChange: (value: string[]) => void;
|
||||
onKeyPress?: (event: KeyboardEvent<HTMLInputElement>) => void;
|
||||
error?: MultiTextInputError;
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
const MultiTextInput = ({ title, value, onChange, onKeyPress, error }: Props) => {
|
||||
const MultiTextInput = ({ title, value, onChange, onKeyPress, error, placeholder }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [deleteFieldIndex, setDeleteFieldIndex] = useState<number>();
|
||||
|
@ -56,6 +57,7 @@ const MultiTextInput = ({ title, value, onChange, onKeyPress, error }: Props) =>
|
|||
error?.inputs?.[fieldIndex] || (fieldIndex === 0 && error?.required)
|
||||
)}
|
||||
value={fieldValue}
|
||||
placeholder={placeholder}
|
||||
onChange={({ currentTarget: { value } }) => {
|
||||
handleInputChange(value, fieldIndex);
|
||||
}}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, { FormEventHandler, KeyboardEventHandler, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import SearchIcon from '@/icons/Search';
|
||||
|
||||
|
@ -15,6 +16,7 @@ type Props = {
|
|||
|
||||
const Search = ({ defaultValue = '', isClearable = false, onSearch, onClearSearch }: Props) => {
|
||||
const [inputValue, setInputValue] = useState<string>(defaultValue);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleSearchKeyPress: KeyboardEventHandler<HTMLInputElement> = (event) => {
|
||||
if (event.key === 'Enter' && inputValue) {
|
||||
|
@ -36,6 +38,7 @@ const Search = ({ defaultValue = '', isClearable = false, onSearch, onClearSearc
|
|||
<TextInput
|
||||
value={inputValue}
|
||||
icon={<SearchIcon className={styles.searchIcon} />}
|
||||
placeholder={t('admin_console.general.search_placeholder')}
|
||||
onChange={handleSearchChange}
|
||||
onKeyPress={handleSearchKeyPress}
|
||||
/>
|
||||
|
|
|
@ -147,6 +147,7 @@ const ApiResourceDetails = () => {
|
|||
{...register('name', { required: true })}
|
||||
hasError={Boolean(errors.name)}
|
||||
readOnly={isLogtoManagementApiResource}
|
||||
placeholder={t('api_resources.api_name_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
|
@ -157,6 +158,9 @@ const ApiResourceDetails = () => {
|
|||
<TextInput
|
||||
{...register('accessTokenTtl', { required: true, valueAsNumber: true })}
|
||||
hasError={Boolean(errors.accessTokenTtl)}
|
||||
placeholder={t(
|
||||
'api_resource_details.token_expiration_time_in_seconds_placeholder'
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Resource } from '@logto/schemas';
|
||||
import React from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Button from '@/components/Button';
|
||||
import FormField from '@/components/FormField';
|
||||
|
@ -23,6 +24,7 @@ const CreateForm = ({ onClose }: Props) => {
|
|||
register,
|
||||
formState: { isSubmitting },
|
||||
} = useForm<FormData>();
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const api = useApi();
|
||||
|
||||
|
@ -53,10 +55,17 @@ const CreateForm = ({ onClose }: Props) => {
|
|||
>
|
||||
<form>
|
||||
<FormField isRequired title="admin_console.api_resources.api_name">
|
||||
<TextInput autoFocus {...register('name', { required: true })} />
|
||||
<TextInput
|
||||
autoFocus
|
||||
{...register('name', { required: true })}
|
||||
placeholder={t('api_resources.api_name_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField isRequired title="admin_console.api_resources.api_identifier">
|
||||
<TextInput {...register('indicator', { required: true })} />
|
||||
<TextInput
|
||||
{...register('indicator', { required: true })}
|
||||
placeholder={t('api_resources.api_identifier_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
</ModalLayout>
|
||||
|
|
|
@ -39,10 +39,17 @@ const Settings = ({ oidcConfig }: Props) => {
|
|||
title="admin_console.application_details.application_name"
|
||||
className={styles.textField}
|
||||
>
|
||||
<TextInput {...register('name', { required: true })} hasError={Boolean(errors.name)} />
|
||||
<TextInput
|
||||
{...register('name', { required: true })}
|
||||
hasError={Boolean(errors.name)}
|
||||
placeholder={t('application_details.application_name_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="admin_console.application_details.description" className={styles.textField}>
|
||||
<TextInput {...register('description')} />
|
||||
<TextInput
|
||||
{...register('description')}
|
||||
placeholder={t('application_details.description_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
title="admin_console.application_details.authorization_endpoint"
|
||||
|
@ -74,6 +81,7 @@ const Settings = ({ oidcConfig }: Props) => {
|
|||
title="admin_console.application_details.redirect_uri"
|
||||
value={value}
|
||||
error={convertRhfErrorMessage(error?.message)}
|
||||
placeholder={t('application_details.redirect_uri_placeholder')}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
|
@ -95,6 +103,7 @@ const Settings = ({ oidcConfig }: Props) => {
|
|||
title="admin_console.application_details.post_sign_out_redirect_uri"
|
||||
value={value}
|
||||
error={convertRhfErrorMessage(error?.message)}
|
||||
placeholder={t('application_details.post_sign_out_redirect_uri_placeholder')}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
|
@ -121,6 +130,7 @@ const Settings = ({ oidcConfig }: Props) => {
|
|||
title="admin_console.application_details.cors_allowed_origins"
|
||||
value={value}
|
||||
error={convertRhfErrorMessage(error?.message)}
|
||||
placeholder={t('application_details.cors_allowed_origins_placeholder')}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -102,10 +102,17 @@ const CreateForm = ({ onClose }: Props) => {
|
|||
)}
|
||||
</FormField>
|
||||
<FormField isRequired title="admin_console.applications.application_name">
|
||||
<TextInput {...register('name', { required: true })} hasError={Boolean(errors.name)} />
|
||||
<TextInput
|
||||
{...register('name', { required: true })}
|
||||
placeholder={t('applications.application_name_placeholder')}
|
||||
hasError={Boolean(errors.name)}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="admin_console.applications.application_description">
|
||||
<TextInput {...register('description')} />
|
||||
<TextInput
|
||||
{...register('description')}
|
||||
placeholder={t('applications.application_description_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
{createdApp && (
|
||||
|
|
|
@ -51,6 +51,7 @@ const BrandingForm = () => {
|
|||
})}
|
||||
hasError={Boolean(errors.branding?.logoUrl)}
|
||||
errorMessage={errors.branding?.logoUrl?.message}
|
||||
placeholder={t('sign_in_exp.branding.logo_image_url_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
{isDarkModeEnabled && (
|
||||
|
@ -61,6 +62,7 @@ const BrandingForm = () => {
|
|||
})}
|
||||
hasError={Boolean(errors.branding?.darkLogoUrl)}
|
||||
errorMessage={errors.branding?.darkLogoUrl?.message}
|
||||
placeholder={t('sign_in_exp.branding.dark_logo_image_url_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
|
@ -68,6 +70,7 @@ const BrandingForm = () => {
|
|||
<TextInput
|
||||
{...register('branding.slogan', { required: isSloganRequired })}
|
||||
hasError={Boolean(errors.branding?.slogan)}
|
||||
placeholder={t('sign_in_exp.branding.slogan_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
</>
|
||||
|
|
|
@ -41,6 +41,7 @@ const TermsForm = () => {
|
|||
})}
|
||||
hasError={Boolean(errors.termsOfUse)}
|
||||
errorMessage={errors.termsOfUse?.contentUrl?.message}
|
||||
placeholder={t('sign_in_exp.terms_of_use.terms_of_use_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
|
|
|
@ -250,6 +250,7 @@ const UserDetails = () => {
|
|||
})}
|
||||
hasError={Boolean(errors.avatar)}
|
||||
errorMessage={errors.avatar?.message}
|
||||
placeholder={t('user_details.field_avatar_placeholder')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
|
|
|
@ -13,6 +13,7 @@ const translation = {
|
|||
retry: 'Try Again',
|
||||
done: 'Done',
|
||||
search: 'Search',
|
||||
search_placeholder: 'Search',
|
||||
clear_result: 'Clear Results',
|
||||
save: 'Save',
|
||||
save_changes: 'Save Changes',
|
||||
|
@ -78,7 +79,9 @@ const translation = {
|
|||
'Setup a mobile, single page or traditional application to use Logto for authentication',
|
||||
create: 'Create Application',
|
||||
application_name: 'Application name',
|
||||
application_name_placeholder: 'My App',
|
||||
application_description: 'Application description',
|
||||
application_description_placeholder: 'Enter your application description',
|
||||
select_application_type: 'Select an application type',
|
||||
no_application_type_selected: 'You haven’t selected any application type yet',
|
||||
application_created:
|
||||
|
@ -117,11 +120,16 @@ const translation = {
|
|||
check_help_guide: 'Check Help Guide',
|
||||
advanced_settings: 'Advanced settings',
|
||||
application_name: 'Application name',
|
||||
application_name_placeholder: 'My App',
|
||||
description: 'Description',
|
||||
description_placeholder: 'Enter your application description',
|
||||
authorization_endpoint: 'Authorization endpoint',
|
||||
redirect_uri: 'Redirect URIs',
|
||||
redirect_uri_placeholder: 'https://myapp.com/sign-in',
|
||||
post_sign_out_redirect_uri: 'Post Sign-out Redirect URIs',
|
||||
post_sign_out_redirect_uri_placeholder: 'https://myapp.com/sign-in',
|
||||
cors_allowed_origins: 'CORS allowed origins',
|
||||
cors_allowed_origins_placeholder: 'https://sign-in.mydomain.com',
|
||||
add_another: 'Add Another',
|
||||
id_token_expiration: 'ID Token expiration',
|
||||
refresh_token_expiration: 'Refresh Token expiration',
|
||||
|
@ -138,12 +146,15 @@ const translation = {
|
|||
subtitle: 'Define APIs that you can consume from your authorized applications.',
|
||||
create: 'Create API Resource',
|
||||
api_name: 'API name',
|
||||
api_name_placeholder: 'Enter your API name',
|
||||
api_identifier: 'API identifier',
|
||||
api_identifier_placeholder: 'https://your-api-identifier/',
|
||||
api_resource_created: 'The API resource {{name}} has been successfully created!',
|
||||
},
|
||||
api_resource_details: {
|
||||
back_to_api_resources: 'Back to API resources',
|
||||
token_expiration_time_in_seconds: 'Token expiration time (in seconds)',
|
||||
token_expiration_time_in_seconds_placeholder: 'Enter your token expiration time',
|
||||
delete_description:
|
||||
'This action cannot be undone. It will permanently delete the API resource. Please enter the api resource name <span>{{name}}</span> to confirm.',
|
||||
enter_your_api_resource_name: 'Enter your API resource name',
|
||||
|
@ -261,6 +272,7 @@ const translation = {
|
|||
field_username: 'Username',
|
||||
field_name: 'Name',
|
||||
field_avatar: 'Avatar image URL',
|
||||
field_avatar_placeholder: 'https://your.cdn.domain/avatar.png',
|
||||
field_custom_data: 'Custom data',
|
||||
field_connectors: 'Social connections',
|
||||
custom_data_invalid: 'Custom data must be a valid JSON',
|
||||
|
@ -325,7 +337,9 @@ const translation = {
|
|||
logo: 'App logo only',
|
||||
},
|
||||
logo_image_url: 'App logo image URL',
|
||||
logo_image_url_placeholder: 'https://your.cdn.domain/logo.png',
|
||||
dark_logo_image_url: 'App logo image URL (Dark)',
|
||||
dark_logo_image_url_placeholder: 'https://your.cdn.domain/logo-dark.png',
|
||||
slogan: 'Slogan',
|
||||
slogan_placeholder: 'Unleash your creativity',
|
||||
},
|
||||
|
@ -334,7 +348,7 @@ const translation = {
|
|||
enable: 'Enable terms of use',
|
||||
description: 'Add the legal agreements for the use of your product',
|
||||
terms_of_use: 'Terms of use',
|
||||
terms_of_use_placeholder: 'Terms of use URL',
|
||||
terms_of_use_placeholder: 'https://your.terms.of.use/',
|
||||
terms_of_use_tip: 'Terms of use URL',
|
||||
},
|
||||
sign_in_methods: {
|
||||
|
|
|
@ -15,6 +15,7 @@ const translation = {
|
|||
retry: '重试',
|
||||
done: '完成',
|
||||
search: '搜索',
|
||||
search_placeholder: '搜索',
|
||||
clear_result: '清除结果',
|
||||
save: '保存',
|
||||
save_changes: '保存更改',
|
||||
|
@ -78,7 +79,9 @@ const translation = {
|
|||
subtitle: '创建一个移动、单页或传统 web 应用程序,并通过 Logto 进行身份验证',
|
||||
create: '创建应用',
|
||||
application_name: '应用名称',
|
||||
application_name_placeholder: '我的应用',
|
||||
application_description: '应用描述',
|
||||
application_description_placeholder: '请输入应用描述',
|
||||
select_application_type: '选择应用类型',
|
||||
no_application_type_selected: '你还没有选择应用类型',
|
||||
application_created: '应用 {{name}} 成功创建! \n现在请完成你的应用设置。',
|
||||
|
@ -114,11 +117,16 @@ const translation = {
|
|||
check_help_guide: '查看帮助引导',
|
||||
advanced_settings: '高级设置',
|
||||
application_name: '应用名称',
|
||||
application_name_placeholder: '我的应用',
|
||||
description: '描述',
|
||||
description_placeholder: '请输入应用描述',
|
||||
authorization_endpoint: 'Authorization Endpoint',
|
||||
redirect_uri: 'Redirect URIs',
|
||||
redirect_uri_placeholder: 'https://myapp.com/sign-in',
|
||||
post_sign_out_redirect_uri: 'Post sign out redirect URIs',
|
||||
post_sign_out_redirect_uri_placeholder: 'https://myapp.com/sign-in',
|
||||
cors_allowed_origins: 'CORS Allowed Origins',
|
||||
cors_allowed_origins_placeholder: 'https://sign-in.mydomain.com',
|
||||
add_another: '新增',
|
||||
id_token_expiration: 'ID Token 过期时间',
|
||||
refresh_token_expiration: 'Refresh Token 过期时间',
|
||||
|
@ -135,12 +143,15 @@ const translation = {
|
|||
subtitle: '定义可以从已授权的应用程序中使用的 API.',
|
||||
create: '创建 API 资源',
|
||||
api_name: 'API 名称',
|
||||
api_name_placeholder: '输入API名称',
|
||||
api_identifier: 'API Identifier',
|
||||
api_identifier_placeholder: 'https://your-api-identifier/',
|
||||
api_resource_created: ' API 资源 {{name}} 已成功创建!',
|
||||
},
|
||||
api_resource_details: {
|
||||
back_to_api_resources: '返回 API 资源',
|
||||
token_expiration_time_in_seconds: 'Token 过期时间(秒)',
|
||||
token_expiration_time_in_seconds_placeholder: '请输入你的 token 过期时间',
|
||||
delete_description:
|
||||
'本操作会永久性地删除该 API 资源,且不可撤销。输入 API 资源名称 <span>{{name}}</span> 确认。',
|
||||
enter_your_api_resource_name: '输入 API 资源名称',
|
||||
|
@ -255,6 +266,7 @@ const translation = {
|
|||
field_username: '用户名',
|
||||
field_name: '姓名',
|
||||
field_avatar: '头像图片链接',
|
||||
field_avatar_placeholder: 'https://your.cdn.domain/avatar.png',
|
||||
field_custom_data: '自定义数据',
|
||||
field_connectors: '社交帐号',
|
||||
custom_data_invalid: '自定义数据必须是有效的 JSON',
|
||||
|
@ -315,16 +327,18 @@ const translation = {
|
|||
logo: '仅有Logo',
|
||||
},
|
||||
logo_image_url: 'Logo 图片 URL',
|
||||
logo_image_url_placeholder: 'https://your.cdn.domain/logo.png',
|
||||
dark_logo_image_url: 'Logo 图片 URL (深色)',
|
||||
dark_logo_image_url_placeholder: 'https://your.cdn.domain/logo-dark.png',
|
||||
slogan: '标语',
|
||||
slogan_placeholder: '释放你的创造力',
|
||||
slogan_placeholder: '释放你的创意',
|
||||
},
|
||||
terms_of_use: {
|
||||
title: '使用条款',
|
||||
enable: '开启使用条款',
|
||||
description: '添加使用产品的法律协议。',
|
||||
terms_of_use: '使用条款',
|
||||
terms_of_use_placeholder: '使用条款 URL',
|
||||
terms_of_use_placeholder: 'https://your.terms.of.use/',
|
||||
terms_of_use_tip: '使用条款 URL',
|
||||
},
|
||||
sign_in_methods: {
|
||||
|
|
Loading…
Reference in a new issue