192 lines
6.8 KiB
TypeScript
192 lines
6.8 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Card } from '../ui/card';
|
|
import { Button } from '../ui/button';
|
|
import { Input } from '../ui/input';
|
|
import { Globe, Copy, Plus, Trash2, CheckCircle, Folder } from 'lucide-react';
|
|
import { useToast } from '../../context/ToastContext';
|
|
|
|
export const ConnectivityView: React.FC = () => {
|
|
const { addToast } = useToast();
|
|
|
|
// WebDAV State
|
|
const [webdavPass, setWebdavPass] = useState('****');
|
|
|
|
// Webhooks State
|
|
const [webhooks, setWebhooks] = useState([
|
|
{
|
|
id: '1',
|
|
url: 'https://api.myapp.com/hooks/veza',
|
|
events: ['file.upload', 'file.delete'],
|
|
},
|
|
]);
|
|
const [newHookUrl, setNewHookUrl] = useState('');
|
|
|
|
const generateWebdavPass = () => {
|
|
setWebdavPass(`wd-${Math.random().toString(36).substr(2, 10)}`);
|
|
addToast('New WebDAV password generated', 'success');
|
|
};
|
|
|
|
const addWebhook = () => {
|
|
if (!newHookUrl) return;
|
|
setWebhooks([
|
|
...webhooks,
|
|
{ id: Date.now().toString(), url: newHookUrl, events: ['file.upload'] },
|
|
]);
|
|
setNewHookUrl('');
|
|
addToast('Webhook endpoint added', 'success');
|
|
};
|
|
|
|
const copyToClipboard = (text: string) => {
|
|
navigator.clipboard.writeText(text);
|
|
addToast('Copied to clipboard');
|
|
};
|
|
|
|
return (
|
|
<div className="h-full flex flex-col gap-8 animate-fadeIn">
|
|
{/* WebDAV Mount Section */}
|
|
<Card variant="default">
|
|
<div className="flex items-start justify-between mb-6">
|
|
<div>
|
|
<h3 className="text-xl font-bold text-white flex items-center gap-2">
|
|
<Folder className="w-5 h-5 text-kodo-gold" /> Directory Mount
|
|
(WebDAV)
|
|
</h3>
|
|
<p className="text-sm text-kodo-content-dim mt-1">
|
|
Access your Cloud Studio files directly from your OS file explorer
|
|
or DAW.
|
|
</p>
|
|
</div>
|
|
<div className="bg-kodo-gold/10 text-kodo-gold px-3 py-1 rounded text-xs font-bold border border-kodo-gold/20">
|
|
PROTOCOL ACTIVE
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 bg-kodo-ink p-6 rounded-xl border border-kodo-steel">
|
|
<div>
|
|
<label className="block text-xs font-bold text-kodo-content-dim uppercase mb-2">
|
|
Server URL
|
|
</label>
|
|
<div className="flex gap-2">
|
|
<div className="flex-1 bg-kodo-graphite border border-kodo-steel rounded px-3 py-2 text-sm text-kodo-text-main font-mono truncate">
|
|
https://webdav.veza.io/u/cyber_producer
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="border border-kodo-steel"
|
|
onClick={() =>
|
|
copyToClipboard('https://webdav.veza.io/u/cyber_producer')
|
|
}
|
|
>
|
|
<Copy className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label className="block text-xs font-bold text-kodo-content-dim uppercase mb-2">
|
|
Username
|
|
</label>
|
|
<div className="flex gap-2">
|
|
<div className="flex-1 bg-kodo-graphite border border-kodo-steel rounded px-3 py-2 text-sm text-kodo-text-main font-mono">
|
|
cyber_producer
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="border border-kodo-steel"
|
|
onClick={() => copyToClipboard('cyber_producer')}
|
|
>
|
|
<Copy className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div className="md:col-span-2">
|
|
<label className="block text-xs font-bold text-kodo-content-dim uppercase mb-2">
|
|
Mount Password
|
|
</label>
|
|
<div className="flex gap-2">
|
|
<div className="flex-1 bg-kodo-graphite border border-kodo-steel rounded px-3 py-2 text-sm text-white font-mono tracking-widest">
|
|
{webdavPass}
|
|
</div>
|
|
<Button variant="secondary" onClick={generateWebdavPass}>
|
|
Generate New
|
|
</Button>
|
|
</div>
|
|
<p className="text-[10px] text-kodo-content-dim mt-2">
|
|
Use this specific password for mounting. Do not use your account
|
|
login password.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
{/* Webhooks Section */}
|
|
<Card variant="default">
|
|
<div className="flex items-start justify-between mb-6">
|
|
<div>
|
|
<h3 className="text-xl font-bold text-white flex items-center gap-2">
|
|
<Globe className="w-5 h-5 text-kodo-cyan" /> Storage Webhooks
|
|
</h3>
|
|
<p className="text-sm text-kodo-content-dim mt-1">
|
|
Trigger actions in external apps when files change.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div className="flex gap-2">
|
|
<Input
|
|
placeholder="https://api.your-app.com/hook"
|
|
value={newHookUrl}
|
|
onChange={(e) => setNewHookUrl(e.target.value)}
|
|
/>
|
|
<Button
|
|
variant="primary"
|
|
icon={<Plus className="w-4 h-4" />}
|
|
onClick={addWebhook}
|
|
>
|
|
Add
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
{webhooks.map((hook) => (
|
|
<div
|
|
key={hook.id}
|
|
className="flex items-center justify-between p-3 bg-kodo-ink rounded border border-kodo-steel"
|
|
>
|
|
<div className="flex-1 min-w-0 mr-4">
|
|
<div className="text-sm font-mono text-white truncate">
|
|
{hook.url}
|
|
</div>
|
|
<div className="text-xs text-kodo-content-dim mt-1 flex gap-2">
|
|
{hook.events.map((ev) => (
|
|
<span key={ev} className="bg-white/5 px-1 rounded">
|
|
{ev}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<div className="text-xs text-kodo-lime flex items-center gap-1">
|
|
<CheckCircle className="w-3 h-3" /> Active
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="text-kodo-red hover:bg-kodo-red/10"
|
|
onClick={() =>
|
|
setWebhooks(webhooks.filter((h) => h.id !== hook.id))
|
|
}
|
|
>
|
|
<Trash2 className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|