mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Allow filtering the list of available edge functions when creating/editing a cron job (#43138)
## Problem Finding a specific edge function is cumbersome when you have many of then. ## Solution Use a combobox instead of a select to allow filtering ## How to test - Enable the cron extension - Enable the pg_net extension - Create a few edge functions - Create a new cron job and select _Supabase edge functions_ You should be able to: - select/unselect an edge function - filter the list to reduce the number of edge functions displayed
This commit is contained in:
1 parent
487c74f174
commit
65dfd228ad
1 file changed
+99
-43
@@ -1,18 +1,29 @@
|
||||
import Link from 'next/link'
|
||||
import { UseFormReturn } from 'react-hook-form'
|
||||
|
||||
import { useParams } from 'common/hooks'
|
||||
import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query'
|
||||
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import { Check, ChevronsUpDown } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useEffect, useId, useMemo, useState } from 'react'
|
||||
import { UseFormReturn } from 'react-hook-form'
|
||||
import {
|
||||
Button,
|
||||
cn,
|
||||
Command_Shadcn_,
|
||||
CommandEmpty_Shadcn_,
|
||||
CommandGroup_Shadcn_,
|
||||
CommandInput_Shadcn_,
|
||||
CommandItem_Shadcn_,
|
||||
CommandList_Shadcn_,
|
||||
FormControl_Shadcn_,
|
||||
FormField_Shadcn_,
|
||||
FormItem_Shadcn_,
|
||||
FormLabel_Shadcn_,
|
||||
FormMessage_Shadcn_,
|
||||
Input,
|
||||
Popover_Shadcn_,
|
||||
PopoverContent_Shadcn_,
|
||||
PopoverTrigger_Shadcn_,
|
||||
ScrollArea,
|
||||
Select_Shadcn_,
|
||||
SelectContent_Shadcn_,
|
||||
SelectItem_Shadcn_,
|
||||
@@ -21,6 +32,7 @@ import {
|
||||
SheetSection,
|
||||
} from 'ui'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
|
||||
import { CreateCronJobForm } from './CreateCronJobSheet/CreateCronJobSheet.constants'
|
||||
|
||||
interface HTTPRequestFieldsProps {
|
||||
@@ -41,19 +53,22 @@ export const EdgeFunctionSection = ({ form }: HTTPRequestFieldsProps) => {
|
||||
isSuccess,
|
||||
isPending: isLoading,
|
||||
} = useEdgeFunctionsQuery({ projectRef: ref })
|
||||
|
||||
const edgeFunctions = useMemo(() => functions ?? [], [functions])
|
||||
const [open, setOpen] = useState(false)
|
||||
const listboxId = useId()
|
||||
const edgeFunctions = useMemo(
|
||||
() =>
|
||||
functions?.map((fn) => ({
|
||||
...fn,
|
||||
url: buildFunctionUrl(fn.slug, selectedProject?.ref || '', selectedProject?.restUrl),
|
||||
})) ?? [],
|
||||
[functions, selectedProject]
|
||||
)
|
||||
|
||||
// Only set a default value if the field is empty
|
||||
useEffect(() => {
|
||||
if (isSuccess && edgeFunctions.length > 0 && !form.getValues('values.edgeFunctionName')) {
|
||||
const fn = edgeFunctions[0]
|
||||
const functionUrl = buildFunctionUrl(
|
||||
fn.slug,
|
||||
selectedProject?.ref || '',
|
||||
selectedProject?.restUrl
|
||||
)
|
||||
form.setValue('values.edgeFunctionName', functionUrl)
|
||||
form.setValue('values.edgeFunctionName', fn.url)
|
||||
}
|
||||
}, [edgeFunctions, form, isSuccess, selectedProject?.ref, selectedProject?.restUrl])
|
||||
|
||||
@@ -84,47 +99,88 @@ export const EdgeFunctionSection = ({ form }: HTTPRequestFieldsProps) => {
|
||||
{edgeFunctions.length === 0 ? (
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm text-foreground-light">Select which edge function to trigger</p>
|
||||
<div className="px-4 py-4 border rounded bg-surface-300 border-strong flex items-center justify-between space-x-4">
|
||||
<p className="text-sm">No edge functions created yet</p>
|
||||
<Button asChild>
|
||||
<Link href={`/project/${ref}/functions`}>Create an edge function</Link>
|
||||
{isLoading ? (
|
||||
<Button type="default" className="justify-start" block size="small" loading>
|
||||
Loading edge functions...
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-4 py-4 border rounded bg-surface-300 border-strong flex items-center justify-between space-x-4">
|
||||
<p className="text-sm">No edge functions created yet</p>
|
||||
<Button asChild>
|
||||
<Link href={`/project/${ref}/functions`}>Create an edge function</Link>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : edgeFunctions.length > 0 ? (
|
||||
<FormField_Shadcn_
|
||||
control={form.control}
|
||||
name="values.edgeFunctionName"
|
||||
render={({ field }) => {
|
||||
const selectedFunction = edgeFunctions.find((fn) => fn.url === field.value)
|
||||
|
||||
return (
|
||||
<FormItem_Shadcn_>
|
||||
<FormLabel_Shadcn_>Edge Function</FormLabel_Shadcn_>
|
||||
<Select_Shadcn_
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
disabled={isLoading}
|
||||
>
|
||||
<FormControl_Shadcn_>
|
||||
<SelectTrigger_Shadcn_>
|
||||
<SelectValue_Shadcn_ placeholder="Select which edge function to trigger" />
|
||||
</SelectTrigger_Shadcn_>
|
||||
</FormControl_Shadcn_>
|
||||
<SelectContent_Shadcn_>
|
||||
{edgeFunctions.map((fn) => {
|
||||
const functionUrl = buildFunctionUrl(
|
||||
fn.slug,
|
||||
selectedProject?.ref || '',
|
||||
selectedProject?.restUrl
|
||||
)
|
||||
|
||||
return (
|
||||
<SelectItem_Shadcn_ key={fn.id} value={functionUrl}>
|
||||
{fn.name}
|
||||
</SelectItem_Shadcn_>
|
||||
)
|
||||
})}
|
||||
</SelectContent_Shadcn_>
|
||||
</Select_Shadcn_>
|
||||
<Popover_Shadcn_ open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger_Shadcn_ asChild>
|
||||
<FormControl_Shadcn_>
|
||||
<Button
|
||||
type="default"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
aria-controls={listboxId}
|
||||
className={cn(
|
||||
'w-full justify-between',
|
||||
!field.value && 'text-muted-foreground'
|
||||
)}
|
||||
size="small"
|
||||
iconRight={
|
||||
<ChevronsUpDown
|
||||
className="ml-2 h-4 w-4 shrink-0 opacity-50"
|
||||
strokeWidth={1}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{selectedFunction
|
||||
? selectedFunction.name
|
||||
: 'Select which edge function to trigger'}
|
||||
</Button>
|
||||
</FormControl_Shadcn_>
|
||||
</PopoverTrigger_Shadcn_>
|
||||
<PopoverContent_Shadcn_ id={listboxId} className="p-0" sameWidthAsTrigger>
|
||||
<Command_Shadcn_>
|
||||
<CommandInput_Shadcn_ placeholder="Search edge functions..." />
|
||||
<CommandList_Shadcn_>
|
||||
<CommandEmpty_Shadcn_>No edge function found.</CommandEmpty_Shadcn_>
|
||||
<CommandGroup_Shadcn_>
|
||||
<ScrollArea className={edgeFunctions.length > 7 ? 'h-[210px]' : ''}>
|
||||
{edgeFunctions.map((fn) => {
|
||||
return (
|
||||
<CommandItem_Shadcn_
|
||||
value={fn.name}
|
||||
key={fn.id}
|
||||
onSelect={() => {
|
||||
field.onChange(fn.url === field.value ? '' : fn.url)
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
fn.url === field.value ? 'opacity-100' : 'opacity-0'
|
||||
)}
|
||||
/>
|
||||
{fn.name}
|
||||
</CommandItem_Shadcn_>
|
||||
)
|
||||
})}
|
||||
</ScrollArea>
|
||||
</CommandGroup_Shadcn_>
|
||||
</CommandList_Shadcn_>
|
||||
</Command_Shadcn_>
|
||||
</PopoverContent_Shadcn_>
|
||||
</Popover_Shadcn_>
|
||||
<FormMessage_Shadcn_ />
|
||||
</FormItem_Shadcn_>
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user