Closed lheng18 closed 2 months ago
@lheng18 Hello there! I'm a bot here to help you with bugs, questions, and becoming a contributor. While you wait for a human maintainer, feel free to ask me anything.
To save user-entered data in a form for personalizations in Dify, you can follow these steps:
zod
to define the structure and validation rules for your form data.react-hook-form
to create the form component.Here is an example based on the provided code:
const accountFormSchema = z.object({
email: z
.string()
.min(1, { message: 'login.error.emailInValid' })
.email('login.error.emailInValid'),
name: z.string().min(1, { message: 'login.error.nameEmpty' }),
password: z.string().min(8, {
message: 'login.error.passwordLengthInValid',
}).regex(validPassword, 'login.error.passwordInvalid'),
});
const InstallForm = () => {
const { t } = useTranslation();
const router = useRouter();
const [showPassword, setShowPassword] = React.useState(false);
const [loading, setLoading] = React.useState(true);
const {
register,
handleSubmit,
formState: { errors },
} = useForm<AccountFormValues>({
resolver: zodResolver(accountFormSchema),
defaultValues: {
name: '',
password: '',
email: '',
},
});
const onSubmit: SubmitHandler<AccountFormValues> = async (data) => {
await setup({
body: {
...data,
},
});
router.push('/signin');
};
const handleSetting = async () => {
handleSubmit(onSubmit)();
};
useEffect(() => {
fetchSetupStatus().then((res: SetupStatusResponse) => {
if (res.step === 'finished') {
window.location.href = '/signin';
} else {
fetchInitValidateStatus().then((res: InitValidateStatusResponse) => {
if (res.status === 'not_started')
window.location.href = '/init';
});
}
setLoading(false);
});
}, []);
return (
loading
? <Loading />
: <>
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="text-[32px] font-bold text-gray-900">{t('login.setAdminAccount')}</h2>
<p className='mt-1 text-sm text-gray-600'>{t('login.setAdminAccountDesc')}</p>
</div>
<div className="grow mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white">
<form onSubmit={handleSubmit(onSubmit)}>
<div className='mb-5'>
<label htmlFor="email" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.email')}
</label>
<div className="mt-1">
<input
{...register('email')}
placeholder={t('login.emailPlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm'}
/>
{errors.email && <span className='text-red-400 text-sm'>{t(`${errors.email?.message}`)}</span>}
</div>
</div>
<div className='mb-5'>
<label htmlFor="name" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.name')}
</label>
<div className="mt-1 relative rounded-md shadow-sm">
<input
{...register('name')}
placeholder={t('login.namePlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm pr-10'}
/>
</div>
{errors.name && <span className='text-red-400 text-sm'>{t(`${errors.name.message}`)}</span>}
</div>
<div className='mb-5'>
<label htmlFor="password" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.password')}
</label>
<div className="mt-1 relative rounded-md shadow-sm">
<input
{...register('password')}
type={showPassword ? 'text' : 'password'}
placeholder={t('login.passwordPlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm pr-10'}
/>
<div className="absolute inset-y-0 right-0 flex items-center pr-3">
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="text-gray-400 hover:text-gray-500 focus:outline-none focus:text-gray-500"
>
{showPassword ? '👀' : '😝'}
</button>
</div>
</div>
<div className={classNames('mt-1 text-xs text-gray-500', {
'text-red-400 !text-sm': errors.password,
})}>{t('login.error.passwordInvalid')}</div>
</div>
<div>
<Button variant='primary' className='w-full' onClick={handleSetting}>
{t('login.installBtn')}
</Button>
</div>
</form>
<div className="block w-hull mt-2 text-xs text-gray-600">
{t('login.license.tip')}
<Link
className='text-primary-600'
target='_blank' rel='noopener noreferrer'
href={'https://docs.dify.ai/user-agreement/open-source'}
>{t('login.license.link')}</Link>
</div>
</div>
</div>
</>
);
};
export default InstallForm;
The onSubmit
function handles the form submission and sends the data to the backend service using the setup
function.
Ensure that the setup
function in your backend service is configured to store the form data in the database. This function should handle the necessary database operations to save the user data.
const onSubmit: SubmitHandler<AccountFormValues> = async (data) => {
await setup({
body: {
...data,
},
});
router.push('/signin');
};
This code snippet demonstrates how to create a custom user registration form in Dify and link it to the database for storing user data [1].
To continue talking to Dosu, mention @dosu.
See this repo https://github.com/crazywoola/dify-tools-worker. You can create an external service to store user related data.
Self Checks
1. Is this request related to a challenge you're experiencing? Tell me about your story.
Need to create a web site that allow users register and enter their own data through forms. How to integrate a regular database to the tool? Thanks!
2. Additional context or comments
No response
3. Can you help us with this feature?