From d3ef78796de8101fd983644c653a54b7e999e434 Mon Sep 17 00:00:00 2001 From: Brummel Date: Mon, 13 Apr 2026 19:23:35 +0200 Subject: [PATCH] Add oneliner to case view Introduce an `oneliner` field to the `CaseView` struct and update the `scan_cases` function to read it from `oneliner.txt`. The `cases.html` template is updated to display the oneliner if present. A new integration test is added to verify the functionality. --- server/src/routes/web.rs | 7 +++++++ server/templates/cases.html | 6 ++++++ server/tests/web_test.rs | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/server/src/routes/web.rs b/server/src/routes/web.rs index d27fb0c..221b483 100644 --- a/server/src/routes/web.rs +++ b/server/src/routes/web.rs @@ -22,6 +22,7 @@ struct CaseView { case_id_short: String, status: String, most_recent: String, + oneliner: Option, recordings: Vec, } @@ -141,6 +142,11 @@ async fn scan_cases(data_path: &Path) -> Vec { .map(|r| r.filename.clone()) .unwrap_or_default(); let case_id_short = case_id.chars().take(8).collect(); + let oneliner = tokio::fs::read_to_string(case_entry.path().join("oneliner.txt")) + .await + .ok() + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()); cases.push(CaseView { user_slug: user_slug.clone(), @@ -148,6 +154,7 @@ async fn scan_cases(data_path: &Path) -> Vec { case_id_short, status: status.to_string(), most_recent, + oneliner, recordings, }); } diff --git a/server/templates/cases.html b/server/templates/cases.html index fa1ffa9..22f7d64 100644 --- a/server/templates/cases.html +++ b/server/templates/cases.html @@ -15,6 +15,7 @@ body { font-family: sans-serif; max-width: 900px; margin: 2em auto; padding: 0 1 .recording-head span { font-family: monospace; font-size: 0.9em; min-width: 20em; } .transcript { margin: 0.5em 0 0 1em; padding: 0.5em; background: #f6f6f6; border-radius: 4px; white-space: pre-wrap; font-family: serif; } .pending { margin: 0.5em 0 0 1em; color: #888; font-style: italic; } +.oneliner { font-size: 1em; color: #333; margin: 0 0 0.3em 0; } @@ -25,6 +26,11 @@ body { font-family: sans-serif; max-width: 900px; margin: 2em auto; padding: 0 1 {% for case in cases %}

{{ case.user_slug }} — {{ case.case_id_short }} ({{ case.status }})

+{% match case.oneliner %} +{% when Some with (t) %} +
{{ t }}
+{% when None %} +{% endmatch %} {{ case.case_id }} {% for rec in case.recordings %}
diff --git a/server/tests/web_test.rs b/server/tests/web_test.rs index b271f12..dab070b 100644 --- a/server/tests/web_test.rs +++ b/server/tests/web_test.rs @@ -98,6 +98,7 @@ async fn web_index_shows_cases() { "Herzkatheter ohne Befund.", ) .unwrap(); + std::fs::write(done_case.join("oneliner.txt"), "Herzkatheter unauffällig").unwrap(); let app = doctate_server::create_router(config); let response = app @@ -122,6 +123,13 @@ async fn web_index_shows_cases() { assert!(body.contains("Transcription pending")); // case2 has a transcript → rendered assert!(body.contains("Herzkatheter ohne Befund.")); + // case2 has an oneliner → rendered exactly once (case1 has none) + assert!(body.contains("Herzkatheter unauffällig")); + assert_eq!( + body.matches("class=\"oneliner\"").count(), + 1, + "expected exactly one oneliner div" + ); let _ = std::fs::remove_dir_all(&data_path); }