feat: Synology WebDAV Integration - Admin-Einstellungen + Datei-Spiegelung

This commit is contained in:
2026-06-14 00:19:00 +02:00
parent d29c3b5530
commit d564323c00
4 changed files with 340 additions and 2 deletions

View File

@@ -2696,6 +2696,104 @@ function UploadShareAdminPanel({ toast }) {
}
// ── WebDAV / Synology NAS Einstellungen ───────────────────────────────────
function WebDavSettings({ toast }) {
const [cfg, setCfg] = useState({ url:'', user:'', password:'', basePath:'/dickendock', enabled:false });
const [testing, setTesting] = useState(false);
const [saving, setSaving] = useState(false);
const [showPw, setShowPw] = useState(false);
useEffect(() => {
api('/admin/webdav').then(d => setCfg(d)).catch(() => {});
}, []);
async function save() {
setSaving(true);
try {
await api('/admin/webdav', { method:'PUT', body: cfg });
toast('WebDAV Einstellungen gespeichert ✓');
} catch(e) { toast('Fehler: ' + e.message); }
finally { setSaving(false); }
}
async function test() {
setTesting(true);
try {
await api('/admin/webdav/test', { body: cfg });
toast('✓ Verbindung erfolgreich!');
} catch(e) { toast('✗ ' + e.message); }
finally { setTesting(false); }
}
const field = (label, key, type='text', placeholder='') => (
<div style={{marginBottom:10}}>
<div style={{color:'rgba(255,255,255,0.4)',fontFamily:'monospace',fontSize:10,marginBottom:4}}>{label}</div>
<div style={{position:'relative'}}>
<input
type={type === 'password' ? (showPw ? 'text' : 'password') : type}
value={cfg[key] || ''}
onChange={e => setCfg(p => ({...p, [key]: e.target.value}))}
placeholder={placeholder}
style={{...S.inp, width:'100%', boxSizing:'border-box', paddingRight: type==='password' ? 36 : 12}}
/>
{type === 'password' && (
<button onClick={()=>setShowPw(v=>!v)}
style={{position:'absolute',right:8,top:'50%',transform:'translateY(-50%)',background:'none',border:'none',color:'rgba(255,255,255,0.4)',cursor:'pointer',fontSize:13}}>
{showPw ? '🙈' : '👁'}
</button>
)}
</div>
</div>
);
return (
<div>
{/* Enable Toggle */}
<div style={{display:'flex',alignItems:'center',gap:10,marginBottom:16,cursor:'pointer'}}
onClick={() => setCfg(p => ({...p, enabled: !p.enabled}))}>
<div style={{
width:36, height:20, borderRadius:10, position:'relative',
background: cfg.enabled ? '#4ade80' : 'rgba(255,255,255,0.1)',
border: `1px solid ${cfg.enabled ? '#4ade80' : 'rgba(255,255,255,0.2)'}`,
transition: 'all 0.2s',
}}>
<div style={{
position:'absolute', top:2, left: cfg.enabled ? 18 : 2,
width:14, height:14, borderRadius:'50%', background:'#fff',
transition: 'left 0.2s',
}}/>
</div>
<span style={{color:cfg.enabled?'#4ade80':'rgba(255,255,255,0.5)',fontFamily:'monospace',fontSize:12}}>
{cfg.enabled ? 'WebDAV aktiv Dateien werden auf NAS gespiegelt' : 'WebDAV deaktiviert'}
</span>
</div>
{field('WEBDAV URL', 'url', 'text', 'http://192.168.1.100:5005 oder https://nas.local:5006')}
{field('BENUTZERNAME', 'user', 'text', 'admin')}
{field('PASSWORT', 'password', 'password', '')}
{field('BASISPFAD AUF DER SYNOLOGY', 'basePath', 'text', '/dickendock')}
<div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:10,marginBottom:16,lineHeight:1.6}}>
Dateien werden unter <span style={{color:'rgba(255,255,255,0.5)'}}>Basispfad/Username/Dateiname</span> gespeichert.<br/>
Beispiel: /dickendock/flo/dokumente/rechnung.pdf<br/>
Synology WebDAV aktivieren: Systemsteuerung Dateidienste WebDAV
</div>
<div style={{display:'flex',gap:8}}>
<button onClick={test} disabled={testing || !cfg.url}
style={{...S.btn('#60a5fa'), opacity:(testing||!cfg.url)?0.5:1}}>
{testing ? '⏳ Teste...' : '🔌 Verbindung testen'}
</button>
<button onClick={save} disabled={saving}
style={{...S.btn('#4ade80'), opacity:saving?0.5:1}}>
{saving ? '⏳...' : '💾 Speichern'}
</button>
</div>
</div>
);
}
function AdminPanel({ toast, mobile, user, nav }) {
const [section, setSection] = useState('profil');
useEffect(() => { if (nav?.section) setSection(nav.section); }, [nav?.ts]);
@@ -2848,6 +2946,9 @@ function AdminPanel({ toast, mobile, user, nav }) {
<Sec title="TMDB API (KINO-FEATURE)">
<TmdbSettings toast={toast}/>
</Sec>
<Sec title="SYNOLOGY NAS / WEBDAV">
<WebDavSettings toast={toast}/>
</Sec>
</div>
)}