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.
This commit is contained in:
2026-04-13 19:23:35 +02:00
parent 33da841087
commit d3ef78796d
3 changed files with 21 additions and 0 deletions
+7
View File
@@ -22,6 +22,7 @@ struct CaseView {
case_id_short: String,
status: String,
most_recent: String,
oneliner: Option<String>,
recordings: Vec<RecordingView>,
}
@@ -141,6 +142,11 @@ async fn scan_cases(data_path: &Path) -> Vec<CaseView> {
.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<CaseView> {
case_id_short,
status: status.to_string(),
most_recent,
oneliner,
recordings,
});
}
+6
View File
@@ -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; }
</style>
</head>
<body>
@@ -25,6 +26,11 @@ body { font-family: sans-serif; max-width: 900px; margin: 2em auto; padding: 0 1
{% for case in cases %}
<div class="case status-{{ case.status }}">
<h2>{{ case.user_slug }} — {{ case.case_id_short }} ({{ case.status }})</h2>
{% match case.oneliner %}
{% when Some with (t) %}
<div class="oneliner">{{ t }}</div>
{% when None %}
{% endmatch %}
<small>{{ case.case_id }}</small>
{% for rec in case.recordings %}
<div class="recording">
+8
View File
@@ -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);
}