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({
|
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')]),
|
type: v.union([v.literal('postgres'), v.literal('supabase')]),
|
||||||
host: v.string(),
|
host: v.string(),
|
||||||
port: v.pipe(
|
port: v.pipe(
|
||||||
|
|
|
@ -14,28 +14,6 @@ import { useAppForm } from '@/components/ui/form/useFormBaseHooks';
|
||||||
import { MultipleInlineFields } from '@/components/ui/form/FormBase';
|
import { MultipleInlineFields } from '@/components/ui/form/FormBase';
|
||||||
import { useDataSourceFormSuccess } from './helpers';
|
import { useDataSourceFormSuccess } from './helpers';
|
||||||
import * as v from 'valibot';
|
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<{
|
export const PostgresForm: React.FC<{
|
||||||
dataSource?: DataSource;
|
dataSource?: DataSource;
|
||||||
|
@ -55,20 +33,22 @@ export const PostgresForm: React.FC<{
|
||||||
password: credentials?.password || '',
|
password: credentials?.password || '',
|
||||||
default_database: credentials?.default_database || '',
|
default_database: credentials?.default_database || '',
|
||||||
default_schema: credentials?.default_schema || '',
|
default_schema: credentials?.default_schema || '',
|
||||||
type: 'postgres',
|
type: credentials?.type || 'postgres',
|
||||||
name: dataSource?.name || credentials?.name || ''
|
name: dataSource?.name || credentials?.name || ''
|
||||||
} as Parameters<typeof createPostgresDataSource>[0],
|
} satisfies PostgresCredentials,
|
||||||
onSubmit: async ({ value }) => {
|
onSubmit: async ({ value, ...rest }) => {
|
||||||
await dataSourceFormSubmit({
|
console.log(rest);
|
||||||
flow,
|
// await dataSourceFormSubmit({
|
||||||
dataSourceId: dataSource?.id,
|
// flow,
|
||||||
onUpdate: () => updateDataSource({ id: dataSource!.id, ...value }),
|
// dataSourceId: dataSource?.id,
|
||||||
onCreate: () => createDataSource(value)
|
// onUpdate: () => updateDataSource({ id: dataSource!.id, ...value }),
|
||||||
});
|
// onCreate: () => createDataSource(value)
|
||||||
|
// });
|
||||||
},
|
},
|
||||||
validators: {
|
validators: {
|
||||||
// onChangeAsyncDebounceMs: 1000,
|
onChangeAsyncDebounceMs: 1000,
|
||||||
onChange: PostgresCredentialsSchema
|
onChangeAsync: PostgresCredentialsSchema,
|
||||||
|
onSubmit: PostgresCredentialsSchema
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -127,37 +107,3 @@ export const PostgresForm: React.FC<{
|
||||||
</FormWrapper>
|
</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 { cn } from '@/lib/classMerge';
|
||||||
import { Button } from '../buttons';
|
import { Button } from '../buttons';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
import { Text } from '../typography';
|
||||||
|
|
||||||
export const { fieldContext, useFieldContext, formContext, useFormContext } =
|
export const { fieldContext, useFieldContext, formContext, useFormContext } =
|
||||||
createFormHookContexts();
|
createFormHookContexts();
|
||||||
|
@ -65,16 +66,33 @@ export function TextField({
|
||||||
type?: Parameters<typeof Input>[0]['type'];
|
type?: Parameters<typeof Input>[0]['type'];
|
||||||
}) {
|
}) {
|
||||||
const field = useFieldContext<string>();
|
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 = (
|
const InputComponent = (
|
||||||
<Input
|
<div className={cn('relative flex w-full flex-col', className)}>
|
||||||
id={field.name}
|
<Input
|
||||||
className={cn('flex-shrink', className)}
|
id={name}
|
||||||
value={field.state.value}
|
className={cn('w-full flex-shrink')}
|
||||||
onChange={(e) => field.handleChange(e.target.value)}
|
value={value}
|
||||||
type={type}
|
onChange={(e) => field.handleChange(e.target.value)}
|
||||||
placeholder={placeholder}
|
type={type}
|
||||||
/>
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
{showError && (
|
||||||
|
<Text className="mt-0.5 text-left" size={'sm'} variant={'danger'}>
|
||||||
|
{error}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (label === null) return InputComponent;
|
if (label === null) return InputComponent;
|
||||||
|
@ -91,7 +109,51 @@ export function TextField({
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NumberField(props: Parameters<typeof TextField>[0]) {
|
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({
|
export function PasswordField({
|
||||||
|
@ -103,15 +165,32 @@ export function PasswordField({
|
||||||
placeholder
|
placeholder
|
||||||
}: Parameters<typeof TextField>[0]) {
|
}: Parameters<typeof TextField>[0]) {
|
||||||
const field = useFieldContext<string>();
|
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 = (
|
const InputComponent = (
|
||||||
<InputPassword
|
<div className={cn('relative flex w-full flex-col', className)}>
|
||||||
id={field.name}
|
<InputPassword
|
||||||
className={cn('flex-shrink', inputClassName)}
|
id={name}
|
||||||
value={field.state.value}
|
className={cn('flex-shrink', inputClassName)}
|
||||||
onChange={(e) => field.handleChange(e.target.value)}
|
value={value}
|
||||||
placeholder={placeholder}
|
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;
|
if (label === null) return InputComponent;
|
||||||
|
|
Loading…
Reference in New Issue