DeployEdgeFunctionButton.tsx132 lines · main
1// @ts-nocheck
2import { useParams } from 'common'
3import { ChevronDown, Code, Terminal } from 'lucide-react'
4import { useRouter } from 'next/router'
5import { parseAsString, useQueryState } from 'nuqs'
6import {
7 AiIconAnimation,
8 DropdownMenu,
9 DropdownMenuContent,
10 DropdownMenuItem,
11 DropdownMenuTrigger,
12} from 'ui'
13
14import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
15import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
16import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
17import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
18import { useIsProjectActive } from '@/hooks/misc/useSelectedProject'
19import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
20import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
21
22export const DeployEdgeFunctionButton = () => {
23 const router = useRouter()
24 const { ref } = useParams()
25 const { data: org } = useSelectedOrganizationQuery()
26
27 const snap = useAiAssistantStateSnapshot()
28 const { openSidebar } = useSidebarManagerSnapshot()
29
30 const { mutate: sendEvent } = useSendEventMutation()
31 const [, setCreateMethod] = useQueryState('create', parseAsString)
32
33 const isProjectActive = useIsProjectActive()
34
35 return (
36 <DropdownMenu>
37 <DropdownMenuTrigger asChild disabled={!isProjectActive}>
38 <ButtonTooltip
39 type="primary"
40 disabled={!isProjectActive}
41 iconRight={<ChevronDown className="w-4 h-4" strokeWidth={1.5} />}
42 tooltip={{
43 content: {
44 side: 'bottom',
45 text: !isProjectActive
46 ? 'Unable to deploy function as project is inactive'
47 : undefined,
48 },
49 }}
50 >
51 Deploy a new function
52 </ButtonTooltip>
53 </DropdownMenuTrigger>
54 <DropdownMenuContent align="end" className="w-80">
55 <DropdownMenuItem
56 onSelect={() => {
57 router.push(`/project/${ref}/functions/new`)
58 sendEvent({
59 action: 'edge_function_via_editor_button_clicked',
60 properties: { origin: 'secondary_action' },
61 groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
62 })
63 }}
64 className="gap-4"
65 >
66 <Code className="shrink-0" size={16} strokeWidth={1.5} />
67 <div>
68 <span className="text-foreground">Via Editor</span>
69 <p>Write and deploy in the browser</p>
70 </div>
71 </DropdownMenuItem>
72 <DropdownMenuItem
73 className="gap-4"
74 onSelect={() => {
75 setCreateMethod('cli')
76 sendEvent({
77 action: 'edge_function_via_cli_button_clicked',
78 properties: { origin: 'secondary_action' },
79 groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
80 })
81 }}
82 >
83 <Terminal className="shrink-0" size={16} strokeWidth={1.5} />
84 <div>
85 <span className="text-foreground">Via CLI</span>
86 <p>Write locally, deploy with the CLI</p>
87 </div>
88 </DropdownMenuItem>
89 <DropdownMenuItem
90 className="gap-4"
91 onSelect={() => {
92 openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
93 snap.newChat({
94 name: 'Create new edge function',
95 initialInput: `Create a new edge function that ...`,
96 suggestions: {
97 title:
98 'I can help you create a new edge function. Here are a few example prompts to get you started:',
99 prompts: [
100 {
101 label: 'Stripe Payments',
102 description: 'Create a new edge function that processes payments with Stripe',
103 },
104 {
105 label: 'Email with Resend',
106 description: 'Create a new edge function that sends emails with Resend',
107 },
108 {
109 label: 'PDF Generator',
110 description:
111 'Create a new edge function that generates PDFs from HTML templates',
112 },
113 ],
114 },
115 })
116 sendEvent({
117 action: 'edge_function_ai_assistant_button_clicked',
118 properties: { origin: 'secondary_action' },
119 groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
120 })
121 }}
122 >
123 <AiIconAnimation className="shrink-0" size={16} />
124 <div>
125 <span className="text-foreground">Via AI Assistant</span>
126 <p>Let the Assistant write and deploy for you</p>
127 </div>
128 </DropdownMenuItem>
129 </DropdownMenuContent>
130 </DropdownMenu>
131 )
132}