Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
parkpow
GitHub Repository: parkpow/deep-license-plate-recognition
Path: blob/master/gate-controller/components/RelaySettingsTab.tsx
1080 views
1
'use client';
2
3
import { useState, useEffect } from 'react';
4
import { invoke } from '@tauri-apps/api/core';
5
import { Button } from '@/components/ui/button';
6
import { Input } from '@/components/ui/input';
7
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
8
import { toast } from 'sonner';
9
import { Copy, Eye, EyeOff, RefreshCw } from 'lucide-react';
10
11
export function RelaySettingsTab() {
12
const [token, setToken] = useState<string | null>(null);
13
const [showToken, setShowToken] = useState(false);
14
15
const fetchToken = async () => {
16
try {
17
const currentToken = await invoke<string | null>('get_webhook_token');
18
setToken(currentToken);
19
} catch (error) {
20
toast.error('Failed to load webhook token', { description: String(error) });
21
}
22
};
23
24
const regenerateToken = async () => {
25
try {
26
const newToken = await invoke<string>('regenerate_webhook_token');
27
setToken(newToken);
28
toast.success('New webhook token generated!');
29
} catch (error) {
30
toast.error('Failed to generate new token', { description: String(error) });
31
}
32
};
33
34
const copyToClipboard = () => {
35
if (token) {
36
navigator.clipboard.writeText(token);
37
toast.success('Token copied to clipboard!');
38
}
39
};
40
41
useEffect(() => {
42
fetchToken();
43
}, []);
44
45
return (
46
<div className="p-4 space-y-6 h-full overflow-y-auto">
47
<Card>
48
<CardHeader>
49
<CardTitle>Webhook Security <span className="text-red-500">*</span></CardTitle>
50
<CardDescription>
51
Protect your webhook endpoint with a secret token. This is mandatory for all API requests. Include this token in the `Authorization` header of your requests as a Bearer token.
52
</CardDescription>
53
</CardHeader>
54
<CardContent className="space-y-4">
55
<div className="flex items-center gap-2">
56
<Input
57
type={showToken ? 'text' : 'password'}
58
readOnly
59
value={token || 'No token generated yet'}
60
className="font-mono"
61
/>
62
<Button variant="outline" size="icon" onClick={() => setShowToken(!showToken)} disabled={!token}>
63
{showToken ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
64
</Button>
65
<Button variant="outline" size="icon" onClick={copyToClipboard} disabled={!token}>
66
<Copy className="w-4 h-4" />
67
</Button>
68
</div>
69
<Button onClick={regenerateToken}>
70
<RefreshCw className="w-4 h-4 mr-2" />
71
{token ? 'Regenerate Token' : 'Generate Token'}
72
</Button>
73
</CardContent>
74
</Card>
75
76
<Card>
77
<CardHeader>
78
<CardTitle>API Usage Example</CardTitle>
79
<CardDescription>Example of how to trigger a relay using `curl`.</CardDescription>
80
</CardHeader>
81
<CardContent className='font-mono text-sm bg-muted p-4 rounded-lg'>
82
<pre><code>
83
{`curl -X POST http://localhost:4848/webhook \
84
-H "Content-Type: application/json" \
85
-H "Authorization: Bearer ${token || '<YOUR_TOKEN>'}" \
86
-d '{ "id": "<YOUR_RELAY_ID>", "action": "on", "channel": 1 }'`}
87
</code></pre>
88
</CardContent>
89
</Card>
90
</div>
91
);
92
}
93
94