Waterfall
thirdshift show <command> --spans --json · thirdshift logs <command>
- Runs {{ view.choices.len() }}{% for choice in view.choices %}{% if choice.selected %} · {{ choice.subject }} · {{ choice.state }}{% endif %}{% endfor %}
-
+ Runs {{ view.choices.len() }}{% for choice in view.choices %}{% if choice.selected %} · {{ choice.subject }}{% match choice.title %}{% when Some with (title) %} · {{ title }}{% when None %}{% endmatch %} · {{ choice.state }}{% endif %}{% endfor %}
+
{% if view.tree.spans.is_empty() %}No Commands yet.
{% else %}
One shared time axis. * marks estimated times. Running calls extend to now.
diff --git a/src/logs/spans.rs b/src/logs/spans.rs
index ece6bfa79..f1db9082d 100644
--- a/src/logs/spans.rs
+++ b/src/logs/spans.rs
@@ -60,6 +60,7 @@ pub(crate) struct Tree {
#[derive(Serialize)]
pub(crate) struct Choice {
pub subject: String,
+ pub title: Option,
pub state: String,
pub url: String,
pub selected: bool,
@@ -231,6 +232,13 @@ pub(crate) fn load(config: &UserConfig, input: &str) -> Result {
let choice = Observation::Record(command).selector().unwrap_or_default();
Choice {
subject: subject(command),
+ title: command.record.issue.as_ref().and_then(|issue| {
+ issue
+ .title
+ .as_ref()
+ .filter(|title| !title.trim().is_empty())
+ .cloned()
+ }),
state: command
.record
.outcome
diff --git a/tests/console/waterfall.rs b/tests/console/waterfall.rs
index 61b9c7edb..b8ff99839 100644
--- a/tests/console/waterfall.rs
+++ b/tests/console/waterfall.rs
@@ -16,6 +16,42 @@ fn start_console(home: &Path, value: &Value) -> Console {
Console::start(Path::new(env!("CARGO_BIN_EXE_thirdshift")), home)
}
+#[test]
+fn waterfall_choices_name_issues_and_keep_untitled_commands_selectable() {
+ let home = tempfile::tempdir().unwrap();
+ configure(home.path());
+ record(home.path(), 7, Some("merged"), 0);
+ let mut untitled = record(home.path(), 8, Some("failed"), 1);
+ untitled["issue"]["title"] = Value::Null;
+ write_record(home.path(), 8, &untitled);
+ let mut experiment = record(home.path(), 9, Some("completed"), 2);
+ experiment["issue"] = Value::Null;
+ experiment["name"] = json!("experiment-fixture");
+ write_record(home.path(), 9, &experiment);
+ let console = Console::start(Path::new(env!("CARGO_BIN_EXE_thirdshift")), home.path());
+ let page = console
+ .get("/waterfall?command=widgets%237")
+ .text()
+ .unwrap();
+ let choices = page
+ .split("")
+ .nth(1)
+ .unwrap()
+ .split(" ")
+ .next()
+ .unwrap();
+ let title = "Widgets <script>alert(1)</script>";
+ let (summary, chips) = choices.split_once("").unwrap();
+ assert!(summary.contains(title), "{summary}");
+ assert!(chips.contains(title), "{chips}");
+ assert!(!choices.contains("