1- import type { PostgresTable , PostgresTrigger } from '@supabase/postgres -meta'
2- import Image from 'next/legacy/image '
3- import { MutableRefObject , useEffect , useMemo , useRef , useState } from 'react'
1+ import { PGTriggerCreate } from '@supabase/pg -meta/src/pg-meta-triggers '
2+ import type { PostgresTrigger } from '@supabase/postgres-meta '
3+ import { useEffect , useMemo , useRef , useState } from 'react'
44import { toast } from 'sonner'
55
66import { useParams } from 'common'
77import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
8- import { FormSection , FormSectionContent , FormSectionLabel } from 'components/ui/Forms/FormSection'
98import { useDatabaseTriggerCreateMutation } from 'data/database-triggers/database-trigger-create-mutation'
109import { useDatabaseTriggerUpdateMutation } from 'data/database-triggers/database-trigger-update-transaction-mutation'
11- import {
12- EdgeFunctionsResponse ,
13- useEdgeFunctionsQuery ,
14- } from 'data/edge-functions/edge-functions-query'
1510import { getTableEditor } from 'data/table-editor/table-editor-query'
1611import { useTablesQuery } from 'data/tables/tables-query'
1712import { isValidHttpUrl , uuidv4 } from 'lib/helpers'
18- import { Button , Checkbox , Form , Input , Listbox , Radio , SidePanel } from 'ui'
13+ import { Button , Form , SidePanel } from 'ui'
1914import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
20- import HTTPRequestFields from './HTTPRequestFields'
21- import { AVAILABLE_WEBHOOK_TYPES , HOOK_EVENTS } from './Hooks.constants'
22- import { PGTriggerCreate } from '@supabase/pg-meta/src/pg-meta-triggers'
15+ import { FormContents } from './FormContents'
2316
2417export interface EditHookPanelProps {
2518 visible : boolean
@@ -29,7 +22,19 @@ export interface EditHookPanelProps {
2922
3023export type HTTPArgument = { id : string ; name : string ; value : string }
3124
32- const EditHookPanel = ( { visible, selectedHook, onClose } : EditHookPanelProps ) => {
25+ export const isEdgeFunction = ( {
26+ ref,
27+ restUrlTld,
28+ url,
29+ } : {
30+ ref ?: string
31+ restUrlTld ?: string
32+ url : string
33+ } ) =>
34+ url . includes ( `https://${ ref } .functions.supabase.${ restUrlTld } /` ) ||
35+ url . includes ( `https://${ ref } .supabase.${ restUrlTld } /functions/` )
36+
37+ export const EditHookPanel = ( { visible, selectedHook, onClose } : EditHookPanelProps ) => {
3338 const { ref } = useParams ( )
3439 const submitRef = useRef < any > ( null )
3540 const [ isEdited , setIsEdited ] = useState ( false )
@@ -49,7 +54,6 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
4954 projectRef : project ?. ref ,
5055 connectionString : project ?. connectionString ,
5156 } )
52- const { data : functions } = useEdgeFunctionsQuery ( { projectRef : ref } )
5357 const [ isSubmitting , setIsSubmitting ] = useState ( false )
5458 const { mutate : createDatabaseTrigger } = useDatabaseTriggerCreateMutation ( {
5559 onSuccess : ( res ) => {
@@ -81,16 +85,12 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
8185 const restUrl = project ?. restUrl
8286 const restUrlTld = restUrl ? new URL ( restUrl ) . hostname . split ( '.' ) . pop ( ) : 'co'
8387
84- const isEdgeFunction = ( url : string ) =>
85- url . includes ( `https://${ ref } .functions.supabase.${ restUrlTld } /` ) ||
86- url . includes ( `https://${ ref } .supabase.${ restUrlTld } /functions/` )
87-
8888 const initialValues = {
8989 name : selectedHook ?. name ?? '' ,
9090 table_id : selectedHook ?. table_id ?? '' ,
9191 http_url : selectedHook ?. function_args ?. [ 0 ] ?? '' ,
9292 http_method : selectedHook ?. function_args ?. [ 1 ] ?? 'POST' ,
93- function_type : isEdgeFunction ( selectedHook ?. function_args ?. [ 0 ] ?? '' )
93+ function_type : isEdgeFunction ( { ref , restUrlTld , url : selectedHook ?. function_args ?. [ 0 ] ?? '' } )
9494 ? 'supabase_function'
9595 : 'http_request' ,
9696 timeout_ms : Number ( selectedHook ?. function_args ?. [ 4 ] ?? 5000 ) ,
@@ -104,7 +104,7 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
104104 if ( selectedHook !== undefined ) {
105105 setEvents ( selectedHook . events )
106106
107- const [ url , method , headers , parameters ] = selectedHook . function_args
107+ const [ _ , __ , headers , parameters ] = selectedHook . function_args
108108
109109 let parsedParameters : Record < string , string > = { }
110110
@@ -314,10 +314,6 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
314314 values = { values }
315315 resetForm = { resetForm }
316316 errors = { errors }
317- projectRef = { ref }
318- restUrlTld = { restUrlTld }
319- functions = { functions }
320- isEdgeFunction = { isEdgeFunction }
321317 tables = { tables }
322318 events = { events }
323319 eventsError = { eventsError }
@@ -352,211 +348,3 @@ const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelProps) =
352348 </ >
353349 )
354350}
355-
356- export default EditHookPanel
357-
358- interface FormContentsProps {
359- values : any
360- resetForm : any
361- errors : any
362- projectRef ?: string
363- restUrlTld ?: string
364- selectedHook ?: PostgresTrigger
365- functions : EdgeFunctionsResponse [ ] | undefined
366- isEdgeFunction : ( url : string ) => boolean
367- tables : PostgresTable [ ]
368- events : string [ ]
369- eventsError ?: string
370- onUpdateSelectedEvents : ( event : string ) => void
371- httpHeaders : HTTPArgument [ ]
372- httpParameters : HTTPArgument [ ]
373- setHttpHeaders : ( arr : HTTPArgument [ ] ) => void
374- setHttpParameters : ( arr : HTTPArgument [ ] ) => void
375- submitRef : MutableRefObject < any >
376- }
377-
378- const FormContents = ( {
379- values,
380- resetForm,
381- errors,
382- projectRef,
383- restUrlTld,
384- selectedHook,
385- functions,
386- isEdgeFunction,
387- tables,
388- events,
389- eventsError,
390- onUpdateSelectedEvents,
391- httpHeaders,
392- httpParameters,
393- setHttpHeaders,
394- setHttpParameters,
395- submitRef,
396- } : FormContentsProps ) => {
397- useEffect ( ( ) => {
398- if ( values . function_type === 'http_request' ) {
399- if ( selectedHook !== undefined ) {
400- const [ url , method ] = selectedHook . function_args
401- const updatedValues = { ...values , http_url : url , http_method : method }
402- resetForm ( { values : updatedValues , initialValues : updatedValues } )
403- } else {
404- const updatedValues = { ...values , http_url : '' }
405- resetForm ( { values : updatedValues , initialValues : updatedValues } )
406- }
407- } else if ( values . function_type === 'supabase_function' ) {
408- const fnSlug = ( functions ?? [ ] ) [ 0 ] ?. slug
409- const defaultFunctionUrl = `https://${ projectRef } .supabase.${ restUrlTld } /functions/v1/${ fnSlug } `
410- const updatedValues = {
411- ...values ,
412- http_url : isEdgeFunction ( values . http_url ) ? values . http_url : defaultFunctionUrl ,
413- }
414- resetForm ( { values : updatedValues , initialValues : updatedValues } )
415- }
416- } , [ values . function_type ] )
417-
418- return (
419- < div >
420- < FormSection header = { < FormSectionLabel className = "lg:!col-span-4" > General</ FormSectionLabel > } >
421- < FormSectionContent loading = { false } className = "lg:!col-span-8" >
422- < Input
423- id = "name"
424- name = "name"
425- label = "Name"
426- descriptionText = "Do not use spaces/whitespaces"
427- />
428- </ FormSectionContent >
429- </ FormSection >
430- < SidePanel . Separator />
431- < FormSection
432- header = {
433- < FormSectionLabel
434- className = "lg:!col-span-4"
435- description = {
436- < p className = "text-sm text-foreground-light" >
437- Select which table and events will trigger your webhook
438- </ p >
439- }
440- >
441- Conditions to fire webhook
442- </ FormSectionLabel >
443- }
444- >
445- < FormSectionContent loading = { false } className = "lg:!col-span-8" >
446- < Listbox
447- size = "medium"
448- id = "table_id"
449- name = "table_id"
450- label = "Table"
451- descriptionText = "This is the table the trigger will watch for changes. You can only select 1 table for a trigger."
452- >
453- < Listbox . Option
454- key = { 'table-no-selection' }
455- id = { 'table-no-selection' }
456- label = { '---' }
457- value = { 'no-selection' }
458- >
459- ---
460- </ Listbox . Option >
461- { tables . map ( ( table ) => (
462- < Listbox . Option
463- key = { table . id }
464- id = { table . id . toString ( ) }
465- value = { table . id }
466- label = { table . name }
467- >
468- < div className = "flex items-center space-x-2" >
469- < p className = "text-foreground-light" > { table . schema } </ p >
470- < p className = "text-foreground" > { table . name } </ p >
471- </ div >
472- </ Listbox . Option >
473- ) ) }
474- </ Listbox >
475- < Checkbox . Group
476- id = "events"
477- name = "events"
478- label = "Events"
479- error = { eventsError }
480- descriptionText = "These are the events that are watched by the webhook, only the events selected above will fire the webhook on the table you've selected."
481- >
482- { HOOK_EVENTS . map ( ( event ) => (
483- < Checkbox
484- key = { event . value }
485- value = { event . value }
486- label = { event . label }
487- description = { event . description }
488- checked = { events . includes ( event . value ) }
489- onChange = { ( ) => onUpdateSelectedEvents ( event . value ) }
490- />
491- ) ) }
492- </ Checkbox . Group >
493- </ FormSectionContent >
494- </ FormSection >
495- < SidePanel . Separator />
496- < FormSection
497- header = {
498- < FormSectionLabel className = "lg:!col-span-4" > Webhook configuration</ FormSectionLabel >
499- }
500- >
501- < FormSectionContent loading = { false } className = "lg:!col-span-8" >
502- < Radio . Group id = "function_type" name = "function_type" label = "Type of webhook" type = "cards" >
503- { AVAILABLE_WEBHOOK_TYPES . map ( ( webhook ) => (
504- < Radio
505- key = { webhook . value }
506- id = { webhook . value }
507- value = { webhook . value }
508- label = ""
509- beforeLabel = {
510- < div className = "flex items-center space-x-5" >
511- < Image src = { webhook . icon } layout = "fixed" width = "32" height = "32" />
512- < div className = "flex-col space-y-0" >
513- < div className = "flex space-x-2" >
514- < p className = "text-foreground" > { webhook . label } </ p >
515- </ div >
516- < p className = "text-foreground-light" > { webhook . description } </ p >
517- </ div >
518- </ div >
519- }
520- />
521- ) ) }
522- </ Radio . Group >
523- </ FormSectionContent >
524- </ FormSection >
525- < SidePanel . Separator />
526-
527- < HTTPRequestFields
528- type = { values . function_type }
529- errors = { errors }
530- httpHeaders = { httpHeaders }
531- httpParameters = { httpParameters }
532- onAddHeader = { ( header ?: any ) => {
533- if ( header ) setHttpHeaders ( httpHeaders . concat ( header ) )
534- else setHttpHeaders ( httpHeaders . concat ( { id : uuidv4 ( ) , name : '' , value : '' } ) )
535- } }
536- onUpdateHeader = { ( idx , property , value ) =>
537- setHttpHeaders (
538- httpHeaders . map ( ( header , i ) => {
539- if ( idx === i ) return { ...header , [ property ] : value }
540- else return header
541- } )
542- )
543- }
544- onRemoveHeader = { ( idx ) => setHttpHeaders ( httpHeaders . filter ( ( _ , i ) => idx !== i ) ) }
545- onAddParameter = { ( ) =>
546- setHttpParameters ( httpParameters . concat ( { id : uuidv4 ( ) , name : '' , value : '' } ) )
547- }
548- onUpdateParameter = { ( idx , property , value ) =>
549- setHttpParameters (
550- httpParameters . map ( ( param , i ) => {
551- if ( idx === i ) return { ...param , [ property ] : value }
552- else return param
553- } )
554- )
555- }
556- onRemoveParameter = { ( idx ) => setHttpParameters ( httpParameters . filter ( ( _ , i ) => idx !== i ) ) }
557- />
558-
559- < button ref = { submitRef } type = "submit" className = "hidden" />
560- </ div >
561- )
562- }
0 commit comments