Files
brittle/brittle-ui/src/pub_detail.rs

109 lines
4.2 KiB
Rust

//! Publication detail: right pane showing full reference fields.
use leptos::prelude::*;
use brittle_model::Reference;
/// Right pane: displays the fields of the currently selected reference.
///
/// When `reference` is `None`, a placeholder is shown.
#[component]
pub fn PubDetail(reference: RwSignal<Option<Reference>>) -> impl IntoView {
use leptos::either::Either;
view! {
<div class="pub-detail-pane">
{move || match reference.get() {
None => Either::Left(view! {
<div class="empty-state">"Select a publication to see details"</div>
}),
Some(r) => Either::Right(view! {
<div class="detail-content">
<h2 class="detail-title">
{r.fields.get("title").cloned().unwrap_or_else(|| "[no title]".into())}
</h2>
<dl class="detail-fields">
// Entry type + cite key
<dt>"Type"</dt>
<dd>{r.entry_type.to_string()}</dd>
<dt>"Cite key"</dt>
<dd class="mono">{r.cite_key.clone()}</dd>
// Authors
{if r.authors.is_empty() {
None
} else {
let names = r.authors.iter()
.map(|p| p.display_name())
.collect::<Vec<_>>()
.join("; ");
Some(view! {
<dt>"Authors"</dt>
<dd>{names}</dd>
})
}}
// Editors
{if r.editors.is_empty() {
None
} else {
let names = r.editors.iter()
.map(|p| p.display_name())
.collect::<Vec<_>>()
.join("; ");
Some(view! {
<dt>"Editors"</dt>
<dd>{names}</dd>
})
}}
// Prioritised well-known fields
{PRIORITY_FIELDS.iter().filter_map(|&key| {
r.fields.get(key).map(|val| view! {
<dt>{field_label(key)}</dt>
<dd>{val.clone()}</dd>
})
}).collect::<Vec<_>>()}
// Remaining fields in alphabetical order
{r.fields.iter()
.filter(|(k, _)| !PRIORITY_FIELDS.contains(&k.as_str())
&& *k != "title")
.map(|(k, v)| view! {
<dt>{field_label(k)}</dt>
<dd>{v.clone()}</dd>
})
.collect::<Vec<_>>()
}
</dl>
<p class="detail-timestamps">
"Modified: "{r.modified_at.format("%Y-%m-%d %H:%M UTC").to_string()}
</p>
</div>
}),
}}
</div>
}
}
/// Fields shown before the alphabetical remainder (excluding "title").
const PRIORITY_FIELDS: &[&str] = &["year", "journal", "booktitle", "volume", "doi", "abstract"];
/// Pretty-print a BibTeX field key.
fn field_label(key: &str) -> String {
match key {
"doi" => "DOI".into(),
"isbn" => "ISBN".into(),
"issn" => "ISSN".into(),
"url" => "URL".into(),
_ => {
let mut s = key.replace('_', " ");
if let Some(c) = s.get_mut(0..1) {
c.make_ascii_uppercase();
}
s
}
}
}