/* ============================================================ WebServicesTab.jsx — Web Servis Entegrasyonu Yönetim Ekranı ============================================================ */ window.WebServicesTab = function WebServicesTab({ toast }) { const { useState, useEffect, useCallback } = React; /* ── State ─────────────────────────────────────────────── */ const [authList, setAuthList] = useState([]); const [serviceList, setServiceList] = useState([]); const [logs, setLogs] = useState([]); const [loading, setLoading] = useState(true); // Modal state const [authModal, setAuthModal] = useState(null); // null | 'new' | {id,...} const [svcModal, setSvcModal] = useState(null); // null | 'new' | {id,...} const [testPanel, setTestPanel] = useState(null); // null | service obj const [authTestPanel, setAuthTestPanel] = useState(null); // null | auth obj const [logsPanel, setLogsPanel] = useState(null); // null | service obj const [activeSection, setActiveSection] = useState('services'); // 'services' | 'auth' /* ── Fetch ─────────────────────────────────────────────── */ const load = useCallback(async () => { setLoading(true); const [a, s] = await Promise.all([ apiFetch('/api/ws/auth'), apiFetch('/api/ws/services'), ]); setAuthList(a || []); setServiceList(s || []); setLoading(false); }, []); useEffect(() => { load(); }, [load]); /* ── Auth CRUD ─────────────────────────────────────────── */ const saveAuth = async (data) => { const isEdit = !!data.id; const url = isEdit ? `/api/ws/auth/${data.id}` : '/api/ws/auth'; const method = isEdit ? 'PUT' : 'POST'; const res = await apiFetch(url, { method, body: JSON.stringify(data) }); if (res?.id) { toast(isEdit ? 'Auth güncellendi' : 'Auth oluşturuldu', 'success'); setAuthModal(null); load(); } }; const deleteAuth = async (id) => { if (!confirm('Auth konfigürasyonu silinsin mi?')) return; await apiFetch(`/api/ws/auth/${id}`, { method: 'DELETE' }); toast('Auth silindi', 'success'); load(); }; /* ── Service CRUD ──────────────────────────────────────── */ const saveSvc = async (data) => { const isEdit = !!data.id; const url = isEdit ? `/api/ws/services/${data.id}` : '/api/ws/services'; const method = isEdit ? 'PUT' : 'POST'; const res = await apiFetch(url, { method, body: JSON.stringify(data) }); if (res?.id) { toast(isEdit ? 'Servis güncellendi' : 'Servis oluşturuldu', 'success'); setSvcModal(null); load(); } }; const deleteSvc = async (id) => { if (!confirm('Servis konfigürasyonu silinsin mi?')) return; await apiFetch(`/api/ws/services/${id}`, { method: 'DELETE' }); toast('Servis silindi', 'success'); load(); }; const toggleActive = async (svc) => { await apiFetch(`/api/ws/services/${svc.id}`, { method: 'PUT', body: JSON.stringify({ ...svc, is_active: !svc.is_active }), }); load(); }; /* ── Logs ──────────────────────────────────────────────── */ const openLogs = async (svc) => { setLogsPanel(svc); const data = await apiFetch(`/api/ws/logs?svc_id=${svc.id}&limit=50`); setLogs(data || []); }; /* ── Render ────────────────────────────────────────────── */ const AUTH_TYPE_LABELS = { oauth2_client_credentials: 'OAuth2 Client Credentials', oauth2_password: 'OAuth2 Password', api_key_header: 'API Key (Header)', api_key_query: 'API Key (Query)', basic_auth: 'Basic Auth', bearer_static: 'Static Bearer Token', custom_header: 'Custom Header', none: 'Auth Yok', }; const METHOD_COLORS = { GET:'#10b981', POST:'#6366f1', PUT:'#f59e0b', PATCH:'#8b5cf6' }; const CT_LABELS = { json:'REST/JSON', soap:'SOAP/XML', xml:'REST/XML', form:'Form', multipart:'Multipart' }; return (
{/* ── Page Header ── */}

Web Servis Entegrasyonları

IVR akışlarından dış servislere bağlantı kurun — kod yazmadan

{loading ? (
Yükleniyor…
) : activeSection === 'auth' ? ( /* ════════════ AUTH SECTION ════════════ */
{authList.length === 0 ? ( ) : (
{authList.map(a => ( setAuthModal(a)} onDelete={() =>deleteAuth(a.id)} onTest={() =>setAuthTestPanel(a)} labels={AUTH_TYPE_LABELS} /> ))}
)}
) : ( /* ════════════ SERVICES SECTION ════════════ */
{serviceList.length === 0 ? ( ) : (
{serviceList.map(s => ( a.id === s.auth_config_id)?.name} methodColors={METHOD_COLORS} ctLabels={CT_LABELS} onEdit={() =>setSvcModal(s)} onDelete={() =>deleteSvc(s.id)} onTest={() =>setTestPanel(s)} onLogs={() =>openLogs(s)} onToggle={() =>toggleActive(s)} /> ))}
)}
)} {/* ── Modals ── */} {authModal !== null && ( setAuthModal(null)} typeLabels={AUTH_TYPE_LABELS} /> )} {svcModal !== null && ( setSvcModal(null)} /> )} {testPanel && ( setTestPanel(null)} toast={toast} /> )} {authTestPanel && ( setAuthTestPanel(null)} toast={toast} /> )} {logsPanel && ( { setLogsPanel(null); setLogs([]); }} /> )}
); }; /* ============================================================ AUTH CARD ============================================================ */ function AuthCard({ auth, onEdit, onDelete, onTest, labels }) { const TYPE_ICONS = { oauth2_client_credentials: 'OAuth2', oauth2_password: 'OAuth2', api_key_header: 'Key', api_key_query: 'Key', basic_auth: 'Basic', bearer_static: 'Bearer', custom_header: 'Custom', none: 'None', }; return (
{auth.name}
{labels[auth.auth_type] || auth.auth_type}
{auth.description && (
{auth.description}
)} {auth.token_url && (
{auth.token_url}
)}
); } /* ============================================================ SERVICE CARD ============================================================ */ function ServiceCard({ svc, authName, methodColors, ctLabels, onEdit, onDelete, onTest, onLogs, onToggle }) { return (
{/* Sol: Bilgiler */}
{svc.name} {/* Method badge */} {svc.method} {/* Content type badge */} {ctLabels[svc.content_type] || svc.content_type} {/* Auth badge */} {authName && ( {authName} )} {svc.trigger_on_call_start && !svc.background_lookup && ( Çağrı başı sorgula )} {svc.trigger_on_call_start && svc.background_lookup && ( Arka planda sorgula )} {!svc.is_active && ( Pasif )}
{/* URL */}
{svc.url}
{/* Response mappings özeti */} {svc.response_mappings?.length > 0 && (
{svc.response_mappings.map((m, i) => ( {m.path} → {m.variable} ))}
)} {svc.description && (
{svc.description}
)}
{/* Sağ: Butonlar */}
); } /* ============================================================ AUTH MODAL ============================================================ */ function AuthModal({ initial, onSave, onClose, typeLabels }) { const { useState } = React; const [form, setForm] = useState({ name: '', description: '', auth_type: 'oauth2_client_credentials', token_url: '', client_id: '', client_secret: '', scope: '', username: '', password: '', api_key: '', api_key_header_name: 'X-API-Key', api_key_query_name: 'api_key', static_token: '', custom_headers: [], token_ttl_override_sec: '', is_active: true, ...initial }); const set = (k, v) =>setForm(f => ({ ...f, [k]: v })); const atype = form.auth_type; return ( set('name', e.target.value)} placeholder="Şirket CRM Token" /> set('description', e.target.value)} /> {/* OAuth2 alanları */} {(atype === 'oauth2_client_credentials' || atype === 'oauth2_password') && (<> set('token_url', e.target.value)} placeholder="https://api.sirket.com/oauth/token" /> set('client_id', e.target.value)} /> set('client_secret', e.target.value)} /> set('scope', e.target.value)} placeholder="read write" /> )} {/* Password ek alanlar */} {(atype === 'oauth2_password' || atype === 'basic_auth') && (<> set('username', e.target.value)} /> set('password', e.target.value)} /> )} {/* API Key */} {atype === 'api_key_header' && (<> set('api_key_header_name', e.target.value)} /> set('api_key', e.target.value)} /> )} {atype === 'api_key_query' && (<> set('api_key_query_name', e.target.value)} /> set('api_key', e.target.value)} /> )} {/* Static Bearer */} {atype === 'bearer_static' && (