fix: improve SPC dashboard UX — hover toolbar, visible report errors

- Change Plotly modebar to hover-only mode to avoid overlapping chart content
- Remove redundant Plotly titles (container headers already provide them)
- Add Content-Type check and inline error display for report downloads
- Fix setup login validation and seed idempotency for existing data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adriano
2026-02-24 16:42:47 +01:00
parent e07a4e4f89
commit 429c94da94
4 changed files with 53 additions and 9 deletions
+21
View File
@@ -268,6 +268,14 @@ async def seed_demo_data(body: PasswordBody):
created_users: list[User] = []
for u in users_data:
# Skip users that already exist
existing = await session.execute(
select(User).where(User.username == u["username"])
)
existing_user = existing.scalar_one_or_none()
if existing_user:
created_users.append(existing_user)
continue
user = User(
username=u["username"],
password_hash=hash_password(u["password"]),
@@ -286,6 +294,19 @@ async def seed_demo_data(body: PasswordBody):
admin_user = created_users[0]
# ---- Recipe -------------------------------------------------------
# Skip if recipe already exists
existing_recipe = await session.execute(
select(Recipe).where(Recipe.code == "DEMO-001")
)
if existing_recipe.scalar_one_or_none():
return {
"status": "ok",
"message": "Demo data already exists, skipped",
"users_created": [u["username"] for u in users_data],
"recipe_created": "DEMO-001",
"measurements_created": 0,
}
recipe = Recipe(
code="DEMO-001",
name="Demo Measurement Recipe",
+7 -2
View File
@@ -603,7 +603,8 @@
showToast('Setup is disabled. Set SETUP_PASSWORD in .env', 'error');
return;
}
// Password accepted (status endpoint is accessible)
// Validate password via init-db (idempotent, no tables needed)
await apiPost('/init-db', { password: pwd });
setupPassword = pwd;
document.getElementById('login-screen').classList.add('hidden');
document.getElementById('setup-panel').classList.remove('hidden');
@@ -611,7 +612,11 @@
await loadUsers();
showToast('Setup panel unlocked', 'success');
} catch (e) {
showToast('Connection error: ' + e.message, 'error');
if (e.message.indexOf('403') !== -1 || e.message.indexOf('Invalid') !== -1) {
showToast('Invalid setup password', 'error');
} else {
showToast('Connection error: ' + e.message, 'error');
}
} finally {
setLoading('btn-login', false);
}