first commit
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import {useEffect, useState} from 'react'
|
||||
import {Link2, Loader2, Rocket} from 'lucide-react'
|
||||
import {useMutation, useQuery} from '@tanstack/react-query'
|
||||
import {createApiGatewayLambdaRoute, listCloudResources} from '@/api/cloudProxyClient'
|
||||
import type {CloudProvider} from '@/types/cloud'
|
||||
import type {CloudResource} from '@/types/resource'
|
||||
|
||||
interface ApiGatewayRoutePanelProps {
|
||||
cloud: CloudProvider
|
||||
resource?: CloudResource
|
||||
runtimeReachable: boolean
|
||||
}
|
||||
|
||||
export function ApiGatewayRoutePanel({cloud, resource, runtimeReachable}: ApiGatewayRoutePanelProps) {
|
||||
const [path, setPath] = useState('/hello')
|
||||
const [method, setMethod] = useState('GET')
|
||||
const [stage, setStage] = useState('dev')
|
||||
const [functionName, setFunctionName] = useState('')
|
||||
const functionsQuery = useQuery({
|
||||
queryKey: ['cloud-resources', cloud, 'serverless'],
|
||||
queryFn: ({signal}) => listCloudResources(cloud, 'serverless', undefined, signal),
|
||||
enabled: cloud === 'aws' && Boolean(resource) && runtimeReachable,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
setPath('/hello')
|
||||
setMethod('GET')
|
||||
setStage('dev')
|
||||
setFunctionName('')
|
||||
}, [resource?.id])
|
||||
|
||||
const routeMutation = useMutation({
|
||||
mutationFn: () => createApiGatewayLambdaRoute(cloud, resource!.id, {path, method, stage, functionName}),
|
||||
})
|
||||
|
||||
if (!resource || resource.service !== 'apigateway') {
|
||||
return (
|
||||
<section className="table-panel">
|
||||
<div className="empty compact">
|
||||
<h3>Select a REST API</h3>
|
||||
<p>Select an API Gateway REST API to connect a route to a Lambda function.</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
const functions = functionsQuery.data?.filter((item) => item.type === 'lambda') ?? []
|
||||
const canCreate = cloud === 'aws' && runtimeReachable && Boolean(functionName) && !routeMutation.isPending
|
||||
|
||||
return (
|
||||
<section className="table-panel">
|
||||
<div className="dynamic-stage-header">
|
||||
<div>
|
||||
<p className="eyebrow">REST API Route</p>
|
||||
<h3><Link2 size={15}/> Connect Lambda</h3>
|
||||
<p className="muted compact-text">Creates and deploys one Lambda proxy route to the selected REST API.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="resource-create-inline">
|
||||
<form className="inspector-action-form apigateway-route-form" onSubmit={(event) => {
|
||||
event.preventDefault()
|
||||
if (canCreate) routeMutation.mutate()
|
||||
}}>
|
||||
<label className="dynamic-field">
|
||||
<span>Route path</span>
|
||||
<input className="input" value={path} onChange={(event) => setPath(event.target.value)} placeholder="/orders" required/>
|
||||
<small>One path segment, for example <code>/qrcode</code>.</small>
|
||||
</label>
|
||||
<label className="dynamic-field">
|
||||
<span>Method</span>
|
||||
<select className="input" value={method} onChange={(event) => setMethod(event.target.value)}>
|
||||
{['GET', 'POST', 'PUT', 'DELETE'].map((value) => <option key={value} value={value}>{value}</option>)}
|
||||
</select>
|
||||
<small>Lambda proxy method.</small>
|
||||
</label>
|
||||
<label className="dynamic-field">
|
||||
<span>Lambda function</span>
|
||||
<select className="input" value={functionName} onChange={(event) => setFunctionName(event.target.value)} required>
|
||||
<option value="">Select a Lambda function</option>
|
||||
{functions.map((fn) => <option key={fn.id} value={fn.name}>{fn.name}</option>)}
|
||||
</select>
|
||||
<small>{functionsQuery.isLoading ? 'Loading functions...' : functions.length === 0 ? 'Create a Lambda function before adding a route.' : 'Receives this route\'s proxy event.'}</small>
|
||||
</label>
|
||||
<label className="dynamic-field">
|
||||
<span>Stage</span>
|
||||
<input className="input" value={stage} onChange={(event) => setStage(event.target.value)} placeholder="dev" required/>
|
||||
<small>Deployment stage name.</small>
|
||||
</label>
|
||||
<button className="button primary apigateway-route-submit" type="submit" disabled={!canCreate}>
|
||||
{routeMutation.isPending ? <Loader2 size={13}/> : <Rocket size={13}/>}
|
||||
{routeMutation.isPending ? 'Deploying' : 'Create and deploy route'}
|
||||
</button>
|
||||
</form>
|
||||
{routeMutation.isError && <p className="error-text compact-text">{routeMutation.error instanceof Error ? routeMutation.error.message : 'Unable to create API route.'}</p>}
|
||||
{routeMutation.data && (
|
||||
<div className="apigateway-route-result">
|
||||
<strong>Route deployed</strong>
|
||||
<a href={routeMutation.data.invokeUrl} target="_blank" rel="noreferrer">{routeMutation.data.invokeUrl}</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user