use chrono::DateTime;
use ratatui::style::{Color, Style};
use ratatui::text::{Line, Span};
use super::{badge, branch, field, short_date};
use crate::api::Build;
use crate::app::App;
pub fn lines(app: &App, build: &Build) -> Vec<Line<'static>> {
let (_, label, color) = status(app, build);
let mut lines = vec![
field(
app,
"Pipeline",
vec![Span::raw(build.definition.name.clone())],
),
field(app, "Run", vec![Span::raw(build.build_number.clone())]),
field(
app,
"Branch",
vec![Span::raw(branch(&build.source_branch).to_string())],
),
field(app, "Status", vec![badge(label, color)]),
];
if let Some(reason) = &build.reason {
lines.push(field(app, "Reason", vec![Span::raw(reason.clone())]));
}
for (label, date) in [
("Queued", &build.queue_time),
("Started", &build.start_time),
("Finished", &build.finish_time),
] {
if let Some(date) = date {
lines.push(field(app, label, vec![Span::raw(short_date(date))]));
}
}
if let Some(duration) = duration(build) {
lines.push(field(app, "Duration", vec![Span::raw(duration)]));
}
lines
}
pub fn line(app: &App, build: &Build) -> Line<'static> {
let muted = Style::new().fg(app.theme.muted);
let (symbol, _, color) = status(app, build);
Line::from(vec![
Span::styled(format!("{symbol} "), Style::new().fg(color)),
Span::raw(build.definition.name.clone()),
Span::styled(format!(" {}", branch(&build.source_branch)), muted),
])
}
pub fn status(app: &App, build: &Build) -> (&'static str, &'static str, Color) {
let theme = &app.theme;
match (build.status.as_str(), build.result.as_deref()) {
("inProgress", _) => ("⟳", "running", theme.build_running),
("cancelling", _) => ("⟳", "cancelling", theme.muted),
("completed", Some("succeeded")) => ("✔", "succeeded", theme.build_succeeded),
("completed", Some("partiallySucceeded")) => ("◑", "partially succeeded", theme.pr_waiting),
("completed", Some("failed")) => ("✖", "failed", theme.build_failed),
("completed", Some("canceled")) => ("⊘", "canceled", theme.muted),
("completed", _) => ("–", "completed", theme.muted),
_ => ("○", "queued", theme.muted),
}
}
fn duration(build: &Build) -> Option<String> {
let parse = |date: &Option<String>| DateTime::parse_from_rfc3339(date.as_deref()?).ok();
let seconds = (parse(&build.finish_time)? - parse(&build.start_time)?).num_seconds();
Some(format!("{}m {}s", seconds / 60, seconds % 60))
}