const API_BASE = window.location.origin; function getTrackingUri() { return document.getElementById('trackingUri').value.trim() || null; } function formatTime(ts) { if (!ts) return ''; const d = new Date(ts); return d.toLocaleDateString('ko-KR') + ' ' + d.toLocaleTimeString('ko-KR', {hour: '2-digit', minute: '2-digit'}); } async function loadExperiments() { const container = document.getElementById('content'); container.innerHTML = '
Loading...
'; const uri = getTrackingUri(); const params = uri ? '?tracking_uri=' + encodeURIComponent(uri) : ''; try { const res = await fetch(API_BASE + '/api/experiments' + params); if (!res.ok) throw new Error('Failed: ' + res.status); const experiments = await res.json(); if (experiments.length === 0) { container.innerHTML = '
No experiments found.
'; return; } container.innerHTML = ''; experiments.forEach(function(exp) { const card = document.createElement('div'); card.className = 'exp-card'; card.innerHTML = '
' + '' + '' + exp.name + '' + '' + exp.run_count + ' runs' + '
' + '
' + '
Loading runs...
' + '
'; container.appendChild(card); }); } catch (e) { container.innerHTML = '
Connection failed: ' + e.message + '
'; } } async function toggleExp(header, expId) { const arrow = header.querySelector('.exp-arrow'); const runList = document.getElementById('runs-' + expId); if (runList.classList.contains('open')) { runList.classList.remove('open'); arrow.classList.remove('open'); return; } arrow.classList.add('open'); runList.classList.add('open'); runList.innerHTML = '
Loading runs...
'; const uri = getTrackingUri(); const params = uri ? '?tracking_uri=' + encodeURIComponent(uri) : ''; try { const res = await fetch(API_BASE + '/api/experiments/' + expId + '/runs' + params); const runs = await res.json(); if (runs.length === 0) { runList.innerHTML = '
No runs
'; return; } runList.innerHTML = ''; runs.forEach(function(run) { const row = document.createElement('div'); row.className = 'run-row'; row.innerHTML = '' + (run.run_name || run.run_id.substring(0, 8)) + '' + '' + run.status + '' + '' + formatTime(run.start_time) + '' + '
' + '' + '' + '' + '
'; runList.appendChild(row); }); } catch (e) { runList.innerHTML = '
Failed to load runs
'; } } async function viewRun(runId) { const uri = getTrackingUri(); const params = uri ? '?tracking_uri=' + encodeURIComponent(uri) : ''; try { const res = await fetch(API_BASE + '/api/runs/' + runId + '/mlflow-link' + params); const data = await res.json(); window.open(data.url, '_blank'); } catch (e) { alert('Failed to get MLflow link'); } } function trainRun(runId) { alert('Train is not implemented yet.'); } function serveRun(runId) { alert('Serve: model_uri required. Use Swagger UI (/docs) for now.'); } document.addEventListener('DOMContentLoaded', function() { loadExperiments(); });