diff --git a/dashboard/src/app/dashboard/environments/page.tsx b/dashboard/src/app/dashboard/environments/page.tsx new file mode 100644 index 0000000..16ab3aa --- /dev/null +++ b/dashboard/src/app/dashboard/environments/page.tsx @@ -0,0 +1,93 @@ +'use client' +import { useEffect, useState } from 'react' +import { Button } from '@/components/ui/button' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { listEnvironments, createEnvironment, deleteEnvironment, type Environment } from '@/lib/api' + +export default function EnvironmentsPage() { + const [envs, setEnvs] = useState([]) + const [error, setError] = useState(null) + const [name, setName] = useState('') + const [body, setBody] = useState('KEY=value') + const [busy, setBusy] = useState(false) + + async function refresh() { + try { setEnvs(await listEnvironments()) } catch (e) { setError(String(e)) } + } + useEffect(() => { refresh() }, []) + + async function create() { + if (!name) return + const values: Record = {} + for (const line of body.split('\n')) { + const t = line.trim() + if (!t || !t.includes('=')) continue + const i = t.indexOf('=') + values[t.slice(0, i).trim()] = t.slice(i + 1).trim() + } + setBusy(true); setError(null) + try { + await createEnvironment(name, values) + setName('') + await refresh() + } catch (e) { setError(String(e)) } finally { setBusy(false) } + } + + async function del(id: string) { + if (!confirm('Delete this environment?')) return + setBusy(true) + try { await deleteEnvironment(id); await refresh() } catch (e) { setError(String(e)) } finally { setBusy(false) } + } + + return ( +
+
+

Environments

+

Named sets of env vars. Attach to a sandbox, a service, or the gateway.

+
+ {error &&

{error}

} + + + New environment + KEY=value per line. + + +
+ + setName(e.target.value)} placeholder="dev-creds" /> +
+
+ +