mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-25 06:36:37 +00:00
Major additions: - Complete Next.js studio application with 1600+ components - Docker support (Dockerfile.combined, docker-compose.yml) - GCP deployment documentation and benchmarks - SQL benchmark scripts for performance testing - Sentry integration for monitoring - Comprehensive test suite and mocks Studio features: - Dashboard and admin interfaces - Data visualization components - Authentication and user management - API integration with RuVector backend - Static data and public assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
import { ChevronDown, Plus, Trash } from 'lucide-react'
|
|
import { useFieldArray } from 'react-hook-form'
|
|
|
|
import { useParams } from 'common'
|
|
import { useApiKeysVisibility } from 'components/interfaces/APIKeys/hooks/useApiKeysVisibility'
|
|
import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query'
|
|
import {
|
|
Button,
|
|
cn,
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
FormControl_Shadcn_,
|
|
FormField_Shadcn_,
|
|
FormItem_Shadcn_,
|
|
FormLabel_Shadcn_,
|
|
FormMessage_Shadcn_,
|
|
Input_Shadcn_,
|
|
SheetSection,
|
|
} from 'ui'
|
|
import { CreateCronJobForm } from './CreateCronJobSheet/CreateCronJobSheet.constants'
|
|
|
|
interface HTTPHeaderFieldsSectionProps {
|
|
variant: 'edge_function' | 'http_request'
|
|
}
|
|
|
|
export const HTTPHeaderFieldsSection = ({ variant }: HTTPHeaderFieldsSectionProps) => {
|
|
// gets the fields through form context
|
|
const { fields, append, remove } = useFieldArray<CreateCronJobForm>({
|
|
name: 'values.httpHeaders',
|
|
})
|
|
|
|
const { ref } = useParams()
|
|
const { canReadAPIKeys } = useApiKeysVisibility()
|
|
const { data: apiKeys } = useAPIKeysQuery(
|
|
{ projectRef: ref, reveal: true },
|
|
{ enabled: canReadAPIKeys }
|
|
)
|
|
|
|
const { serviceKey, secretKey } = getKeys(apiKeys)
|
|
const apiKey = secretKey?.api_key ?? serviceKey?.api_key ?? '[YOUR API KEY]'
|
|
|
|
return (
|
|
<SheetSection>
|
|
<FormLabel_Shadcn_>HTTP Headers</FormLabel_Shadcn_>
|
|
<div className="space-y-3 mt-1">
|
|
{fields.map((field, index) => (
|
|
<div key={field.id} className="flex items-center space-x-2">
|
|
<FormField_Shadcn_
|
|
name={`values.httpHeaders.${index}.name`}
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="flex-1">
|
|
<FormControl_Shadcn_>
|
|
<Input_Shadcn_
|
|
{...field}
|
|
size="small"
|
|
className="w-full"
|
|
placeholder="Header name"
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<FormMessage_Shadcn_ />
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
<FormField_Shadcn_
|
|
name={`values.httpHeaders.${index}.value`}
|
|
render={({ field }) => (
|
|
<FormItem_Shadcn_ className="flex-1">
|
|
<FormControl_Shadcn_>
|
|
<Input_Shadcn_
|
|
{...field}
|
|
value={field.value}
|
|
size="small"
|
|
className="w-full"
|
|
placeholder="Header value"
|
|
/>
|
|
</FormControl_Shadcn_>
|
|
<FormMessage_Shadcn_ />
|
|
</FormItem_Shadcn_>
|
|
)}
|
|
/>
|
|
|
|
<Button
|
|
type="default"
|
|
icon={<Trash size={12} />}
|
|
onClick={() => remove(index)}
|
|
className="h-[34px] w-[34px]"
|
|
/>
|
|
</div>
|
|
))}
|
|
<div className="flex items-center">
|
|
<Button
|
|
type="default"
|
|
size="tiny"
|
|
icon={<Plus />}
|
|
className={cn(variant === 'edge_function' && 'rounded-r-none px-3 border-r-0')}
|
|
onClick={() => append({ name: '', value: '' })}
|
|
>
|
|
Add a new header
|
|
</Button>
|
|
{variant === 'edge_function' && (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button type="default" className="rounded-l-none px-[4px] py-[5px]">
|
|
<ChevronDown size={14} />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" side="bottom">
|
|
<DropdownMenuItem
|
|
key="add-auth-header"
|
|
onClick={() => {
|
|
append({
|
|
name: 'Authorization',
|
|
value: `Bearer ${apiKey}`,
|
|
})
|
|
if (serviceKey?.type === 'secret') {
|
|
append({ name: 'apikey', value: apiKey })
|
|
}
|
|
}}
|
|
>
|
|
<div className="space-y-1">
|
|
<p className="block text-foreground">Add auth header with secret key</p>
|
|
<p className="text-foreground-light">
|
|
Required if your edge function enforces JWT verification
|
|
</p>
|
|
</div>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem
|
|
key="add-source-header"
|
|
onClick={() =>
|
|
append({
|
|
name: 'x-supabase-webhook-source',
|
|
value: `[Use a secret value]`,
|
|
})
|
|
}
|
|
>
|
|
<div className="space-y-1">
|
|
<p className="block text-foreground">Add custom source header</p>
|
|
<p className="text-foreground-light">
|
|
Useful to verify that the edge function was triggered from this webhook
|
|
</p>
|
|
</div>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</SheetSection>
|
|
)
|
|
}
|