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:
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user