0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(console): add custom domain form (#3962)

This commit is contained in:
Xiao Yijun 2023-06-06 17:24:48 +08:00 committed by GitHub
parent 0c1744e77d
commit 6fcc2a875c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 128 additions and 2 deletions

View file

@ -0,0 +1,15 @@
@use '@/scss/underscore' as _;
.addDomain {
width: 100%;
display: flex;
.textInput {
flex: 1;
margin-right: _.unit(3);
}
.addButton {
flex-shrink: 0;
}
}

View file

@ -0,0 +1,71 @@
import { type Domain } from '@logto/schemas';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import Button from '@/components/Button';
import TextInput from '@/components/TextInput';
import useApi from '@/hooks/use-api';
import { onKeyDownHandler } from '@/utils/a11y';
import * as styles from './index.module.scss';
const subdomainRegex = /^[\dA-Za-z][\dA-Za-z-]*[\dA-Za-z](\.[\dA-Za-z][\dA-Za-z-]*[\dA-Za-z]){2,}$/;
type FormData = {
domain: string;
};
type Props = {
onCustomDomainAdded: (domain: Domain) => void;
};
function AddDomainForm({ onCustomDomainAdded }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const {
register,
watch,
formState: { errors, isSubmitting },
handleSubmit,
} = useForm<FormData>({
defaultValues: {
domain: '',
},
});
const domainInput = watch('domain');
const api = useApi();
const onSubmit = handleSubmit(async (formData) => {
const createdDomain = await api.post('api/domains', { json: formData }).json<Domain>();
onCustomDomainAdded(createdDomain);
});
return (
<div className={styles.addDomain}>
<TextInput
className={styles.textInput}
placeholder={t('domain.custom.custom_domain_placeholder')}
error={errors.domain?.message}
onKeyDown={onKeyDownHandler({ Enter: onSubmit })}
{...register('domain', {
required: true,
pattern: {
value: subdomainRegex,
message: t('domain.custom.invalid_domain_format'),
},
})}
/>
<Button
className={styles.addButton}
type="primary"
title="domain.custom.add_domain"
isLoading={isSubmitting}
disabled={domainInput.length === 0}
onClick={onSubmit}
/>
</div>
);
}
export default AddDomainForm;

View file

@ -0,0 +1,7 @@
@use '@/scss/underscore' as _;
.container {
> div:not(:first-child) {
margin-top: _.unit(4);
}
}

View file

@ -1,12 +1,45 @@
import { type Domain } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
import useSWR from 'swr';
import FormCard from '@/components/FormCard';
import FormField from '@/components/FormField';
import { type RequestError } from '@/hooks/use-api';
import AddDomainForm from './components/AddDomainForm';
import DefaultDomain from './components/DefaultDomain';
import * as styles from './index.module.scss';
function TenantDomainSettings() {
// Todo: @xiaoyijun setup the auto refresh interval for the domains when implementing the active domain process.
const { data, error, mutate } = useSWR<Domain[], RequestError>('api/domains');
const isLoading = !data && !error;
/**
* Note: we can only create a custom domain, and we don't have a default id for it, so the first element of the array is the custom domain.
*/
const customDomain = conditional(!isLoading && data)?.[0];
if (isLoading) {
return null;
}
return (
<div>
{/* TODO: @xiaoyijun add the custom domain form card */}
<div className={styles.container}>
<FormCard
title="domain.custom.custom_domain"
description="domain.custom.custom_domain_description"
>
<FormField title="domain.custom.custom_domain_field">
{!customDomain && (
<AddDomainForm
onCustomDomainAdded={(domain) => {
void mutate([domain]);
}}
/>
)}
{/* TODO @xiaoyijun add custom domain content if a custom domain is created */}
</FormField>
</FormCard>
<FormCard
title="domain.default.default_domain"
description="domain.default.default_domain_description"