mirror of https://github.com/buster-so/buster.git
validator update
This commit is contained in:
parent
1d37f2fe2f
commit
550dda19ca
|
@ -57,7 +57,7 @@ export enum DataSourceEnvironment {
|
|||
}
|
||||
|
||||
export const PostgresCredentialsSchema = v.object({
|
||||
name: v.string(),
|
||||
name: v.pipe(v.string(), v.minLength(3, 'Name must be at least 3 characters')),
|
||||
type: v.union([v.literal('postgres'), v.literal('supabase')]),
|
||||
host: v.string(),
|
||||
port: v.pipe(
|
||||
|
|
|
@ -14,28 +14,6 @@ import { useAppForm } from '@/components/ui/form/useFormBaseHooks';
|
|||
import { MultipleInlineFields } from '@/components/ui/form/FormBase';
|
||||
import { useDataSourceFormSuccess } from './helpers';
|
||||
import * as v from 'valibot';
|
||||
import { useForm } from '@tanstack/react-form';
|
||||
|
||||
const ValibotSchema = v.object({
|
||||
// firstName: v.pipe(
|
||||
// v.string(),
|
||||
// v.minLength(3, '[Valibot] You must have a length of at least 3'),
|
||||
// v.startsWith('A', "[Valibot] First name must start with 'A'")
|
||||
// ),
|
||||
// lastName: v.pipe(v.string(), v.minLength(3, '[Valibot] You must have a length of at least 3'))
|
||||
name: v.string(),
|
||||
type: v.union([v.literal('postgres'), v.literal('supabase')]),
|
||||
host: v.string(),
|
||||
port: v.pipe(
|
||||
v.number(),
|
||||
v.minValue(1, 'Port must be greater than 0'),
|
||||
v.maxValue(65535, 'Port must be less than or equal to 65535')
|
||||
),
|
||||
username: v.string(),
|
||||
password: v.string(),
|
||||
default_database: v.string(), // postgres
|
||||
default_schema: v.string() // public
|
||||
});
|
||||
|
||||
export const PostgresForm: React.FC<{
|
||||
dataSource?: DataSource;
|
||||
|
@ -55,20 +33,22 @@ export const PostgresForm: React.FC<{
|
|||
password: credentials?.password || '',
|
||||
default_database: credentials?.default_database || '',
|
||||
default_schema: credentials?.default_schema || '',
|
||||
type: 'postgres',
|
||||
type: credentials?.type || 'postgres',
|
||||
name: dataSource?.name || credentials?.name || ''
|
||||
} as Parameters<typeof createPostgresDataSource>[0],
|
||||
onSubmit: async ({ value }) => {
|
||||
await dataSourceFormSubmit({
|
||||
flow,
|
||||
dataSourceId: dataSource?.id,
|
||||
onUpdate: () => updateDataSource({ id: dataSource!.id, ...value }),
|
||||
onCreate: () => createDataSource(value)
|
||||
});
|
||||
} satisfies PostgresCredentials,
|
||||
onSubmit: async ({ value, ...rest }) => {
|
||||
console.log(rest);
|
||||
// await dataSourceFormSubmit({
|
||||
// flow,
|
||||
// dataSourceId: dataSource?.id,
|
||||
// onUpdate: () => updateDataSource({ id: dataSource!.id, ...value }),
|
||||
// onCreate: () => createDataSource(value)
|
||||
// });
|
||||
},
|
||||
validators: {
|
||||
// onChangeAsyncDebounceMs: 1000,
|
||||
onChange: PostgresCredentialsSchema
|
||||
onChangeAsyncDebounceMs: 1000,
|
||||
onChangeAsync: PostgresCredentialsSchema,
|
||||
onSubmit: PostgresCredentialsSchema
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -127,37 +107,3 @@ export const PostgresForm: React.FC<{
|
|||
</FormWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const Test2 = () => {
|
||||
const flow = 'create';
|
||||
const dataSourceFormSubmit = useDataSourceFormSuccess();
|
||||
|
||||
const form2 = useForm({
|
||||
defaultValues: {
|
||||
host: 'test',
|
||||
port: 5432,
|
||||
username: 'test',
|
||||
password: 'test',
|
||||
default_database: 'test',
|
||||
default_schema: 'test',
|
||||
type: 'postgres',
|
||||
name: 'test'
|
||||
} satisfies Parameters<typeof createPostgresDataSource>[0],
|
||||
onSubmit: async ({ value }) => {
|
||||
await dataSourceFormSubmit({
|
||||
flow,
|
||||
dataSourceId: '123',
|
||||
onUpdate: async () => {},
|
||||
onCreate: async () => {}
|
||||
});
|
||||
},
|
||||
validators: {
|
||||
// DEMO: You can switch between schemas seamlessly
|
||||
// onChange: ZodSchema,
|
||||
onChange: ValibotSchema
|
||||
// onChange: ArkTypeSchema,
|
||||
}
|
||||
});
|
||||
|
||||
return <div>Test2</div>;
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@ import { InputPassword } from '../inputs/InputPassword';
|
|||
import { cn } from '@/lib/classMerge';
|
||||
import { Button } from '../buttons';
|
||||
import { ReactNode } from 'react';
|
||||
import { Text } from '../typography';
|
||||
|
||||
export const { fieldContext, useFieldContext, formContext, useFormContext } =
|
||||
createFormHookContexts();
|
||||
|
@ -65,16 +66,33 @@ export function TextField({
|
|||
type?: Parameters<typeof Input>[0]['type'];
|
||||
}) {
|
||||
const field = useFieldContext<string>();
|
||||
const {
|
||||
name,
|
||||
state: {
|
||||
value,
|
||||
meta: { errors, isTouched }
|
||||
}
|
||||
} = field;
|
||||
const error = errors?.[0]?.message;
|
||||
const isFormSubmitted = field.form.state.submissionAttempts > 1;
|
||||
const showError = !!error && (isFormSubmitted || isTouched);
|
||||
|
||||
const InputComponent = (
|
||||
<Input
|
||||
id={field.name}
|
||||
className={cn('flex-shrink', className)}
|
||||
value={field.state.value}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
<div className={cn('relative flex w-full flex-col', className)}>
|
||||
<Input
|
||||
id={name}
|
||||
className={cn('w-full flex-shrink')}
|
||||
value={value}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
{showError && (
|
||||
<Text className="mt-0.5 text-left" size={'sm'} variant={'danger'}>
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (label === null) return InputComponent;
|
||||
|
@ -91,7 +109,51 @@ export function TextField({
|
|||
}
|
||||
|
||||
export function NumberField(props: Parameters<typeof TextField>[0]) {
|
||||
return <TextField {...props} type="number" />;
|
||||
const field = useFieldContext<number>();
|
||||
const isFormSubmitted = field.form.state.submissionAttempts > 1;
|
||||
const {
|
||||
name,
|
||||
state: {
|
||||
value,
|
||||
meta: { errors, isTouched }
|
||||
}
|
||||
} = field;
|
||||
const error = errors?.[0]?.message;
|
||||
|
||||
const showError = !!error && (isFormSubmitted || isTouched);
|
||||
|
||||
const InputComponent = (
|
||||
<div className={cn('relative flex w-full flex-col', props.className)}>
|
||||
<Input
|
||||
id={name}
|
||||
className={cn('w-full flex-shrink')}
|
||||
value={value ?? ''}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value === '' ? 0 : Number(e.target.value);
|
||||
field.handleChange(val);
|
||||
}}
|
||||
type="number"
|
||||
placeholder={props.placeholder}
|
||||
/>
|
||||
{showError && (
|
||||
<Text className="mt-0.5 text-left" size={'sm'} variant={'danger'}>
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (props.label === null) return InputComponent;
|
||||
|
||||
return (
|
||||
<LabelWrapper
|
||||
label={props.label}
|
||||
direction={props.direction}
|
||||
labelClassName={props.labelClassName}
|
||||
htmlFor={field.name}>
|
||||
{InputComponent}
|
||||
</LabelWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export function PasswordField({
|
||||
|
@ -103,15 +165,32 @@ export function PasswordField({
|
|||
placeholder
|
||||
}: Parameters<typeof TextField>[0]) {
|
||||
const field = useFieldContext<string>();
|
||||
const {
|
||||
name,
|
||||
state: {
|
||||
value,
|
||||
meta: { errors, isTouched }
|
||||
}
|
||||
} = field;
|
||||
const error = errors?.[0]?.message;
|
||||
const isFormSubmitted = field.form.state.submissionAttempts > 1;
|
||||
const showError = !!error && (isFormSubmitted || isTouched);
|
||||
|
||||
const InputComponent = (
|
||||
<InputPassword
|
||||
id={field.name}
|
||||
className={cn('flex-shrink', inputClassName)}
|
||||
value={field.state.value}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
<div className={cn('relative flex w-full flex-col', className)}>
|
||||
<InputPassword
|
||||
id={name}
|
||||
className={cn('flex-shrink', inputClassName)}
|
||||
value={value}
|
||||
onChange={(e) => field.handleChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
{showError && (
|
||||
<Text className="mt-0.5 text-left" size={'sm'} variant={'danger'}>
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (label === null) return InputComponent;
|
||||
|
|
Loading…
Reference in New Issue