diff --git a/src/fgai/dashboard.py b/src/fgai/dashboard.py index 2cbdda9..6fa4780 100644 --- a/src/fgai/dashboard.py +++ b/src/fgai/dashboard.py @@ -110,6 +110,9 @@ HTML = """ .stream-row label { min-width: 0; display: flex; align-items: center; gap: 7px; } .stream-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .stream-row button, .stream-tools button { border: 1px solid #39709a; background: #0b2944; color: #d9e8f7; padding: 5px 8px; cursor: pointer; white-space: nowrap; } + .stream-actions, .profile-actions { display: inline-flex; gap: 6px; align-items: center; justify-content: flex-end; } + .small-action { padding: 3px 6px !important; font-size: 12px; line-height: 1.2; } + .danger-action { border-color: #7f3c48 !important; color: #ffb4bf !important; background: #2a1720 !important; } .toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 8px 0 12px; color: #91abc4; } .toolbar label { display: inline-flex; align-items: center; gap: 6px; } .summary-card { border: 1px solid #163b59; background: #061a2e; padding: 10px; margin-bottom: 8px; border-radius: 6px; } @@ -669,7 +672,7 @@ async function refresh() { {label:'Common denominators', render:r => esc((r.common_fields || []).slice(0,5).map(item => `${item.field} ${(item.coverage*100).toFixed(0)}%`).join(', ') || '-')}, {label:'Shared fields', render:r => esc((r.shared_fields || []).slice(0,4).map(sharedFieldLabel).join(', ') || '-')}, {label:'Discovery', render:r => profileDiscoveryDetails(r)}, - {label:'Action', render:r => `${r.profile_exists ? ` ` : ''}`} + {label:'Action', render:r => `${r.profile_exists ? ` ` : ''}`} ], 'profile-suggestions') : '

No missing stream profiles. Enable "show existing profiles" to inspect already configured profiles.

'; const llmText = llm.text ? esc(llm.text).replace(/\\n/g, '
') : esc(llm.error || 'LLM assessment disabled or waiting for first run.'); document.getElementById('llmAssessment').innerHTML = `
Status: ${esc(llm.status || (llmEnabled ? 'starting' : 'disabled'))}

${llmText}

`; @@ -945,7 +948,7 @@ function renderStreamPicker(errorText='') {
${streams.map(stream => { const selected = window.streamSelection[stream.id] || {id:stream.id, title:stream.title, enabled:false}; const hasProfile = (window.streamProfiles || []).some(profile => String(profile.stream_id) === String(stream.id)); - return `
${hasProfile ? `` : ''}
`; + return `
${hasProfile ? `` : ''}
`; }).join('')}
`; document.getElementById('streamFilter').addEventListener('input', () => renderStreamPicker()); document.getElementById('streamEnabledOnly').addEventListener('change', () => renderStreamPicker()); diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index 556a9ab..110abc3 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -35,9 +35,10 @@ class DashboardTests(unittest.TestCase): self.assertIn("function mergeProfile", HTML) def test_dashboard_can_delete_stream_profiles(self): - self.assertIn("Delete profile", HTML) + self.assertIn("Remove", HTML) self.assertIn("function deleteStreamProfile", HTML) self.assertIn("delete-stream-profile", HTML) + self.assertIn("danger-action", HTML) def test_dashboard_has_direct_stream_selection_save(self): self.assertIn("Save streams", HTML)