From a9843a08cfda2f8f8b19878294b12c08dbb3f095 Mon Sep 17 00:00:00 2001 From: Amolith Date: Wed, 18 Mar 2026 23:28:49 -0600 Subject: [PATCH] Display labels in CLI and web table views --- src/cmd/list.rs | 5 ++++- src/cmd/next.rs | 15 +++++++++++++-- src/cmd/webui/project/mod.rs | 12 ++++++++++++ src/cmd/webui/project/views.rs | 2 ++ src/cmd/webui/task/mod.rs | 1 + templates/macros.html | 2 ++ templates/project.html | 2 ++ templates/task.html | 2 ++ 8 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/cmd/list.rs b/src/cmd/list.rs index e5cda01a65430f9adefcbf0b73df2d4c9f48ed01..caae8962d139f2befe5ebf40354aae8fa3c9b7ed 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -58,7 +58,9 @@ pub fn run(root: &Path, opts: Opts) -> Result<()> { let use_color = stdout_use_color(); let mut table = Table::new(); table.load_preset(NOTHING); - table.set_header(vec!["ID", "STATUS", "TYPE", "PRIORITY", "EFFORT", "TITLE"]); + table.set_header(vec![ + "ID", "STATUS", "TYPE", "PRIORITY", "EFFORT", "LABELS", "TITLE", + ]); for t in &tasks { table.add_row(vec![ cell_bold(&t.id, use_color), @@ -66,6 +68,7 @@ pub fn run(root: &Path, opts: Opts) -> Result<()> { Cell::new(&t.task_type), cell_priority(t.priority.as_str(), t.priority, use_color), cell_effort(t.effort.as_str(), t.effort, use_color), + Cell::new(t.labels.join(", ")), Cell::new(&t.title), ]); } diff --git a/src/cmd/next.rs b/src/cmd/next.rs index 19d6d44fa55fc90187e31bec7d194543a47f6e16..664be7e2aed1303eba2b1d0a0fa3e5aa48e9c278 100644 --- a/src/cmd/next.rs +++ b/src/cmd/next.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use comfy_table::presets::NOTHING; use comfy_table::{Cell, Table}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::path::Path; use crate::color::{cell_bold, stdout_use_color}; @@ -60,6 +60,12 @@ pub fn run(root: &Path, mode_str: &str, verbose: bool, limit: usize, json: bool) limit, ); + // Build a lookup from task ID to labels for display. + let labels_by_id: HashMap<&str, &[String]> = all + .iter() + .map(|t| (t.id.as_str(), t.labels.as_slice())) + .collect(); + if scored.is_empty() { if json { println!("[]"); @@ -94,14 +100,19 @@ pub fn run(root: &Path, mode_str: &str, verbose: bool, limit: usize, json: bool) let use_color = stdout_use_color(); let mut table = Table::new(); table.load_preset(NOTHING); - table.set_header(vec!["#", "ID", "SCORE", "TITLE"]); + table.set_header(vec!["#", "ID", "SCORE", "LABELS", "TITLE"]); for (i, s) in scored.iter().enumerate() { let short = TaskId::display_id(&s.id); + let labels = labels_by_id + .get(s.id.as_str()) + .map(|ls| ls.join(", ")) + .unwrap_or_default(); table.add_row(vec![ Cell::new(i + 1), cell_bold(&short, use_color), Cell::new(format!("{:.2}", s.score)), + Cell::new(labels), Cell::new(&s.title), ]); } diff --git a/src/cmd/webui/project/mod.rs b/src/cmd/webui/project/mod.rs index d047e3efabdaafedbb35ed34779c99b73a6e41f9..dfb7e1965c75c9c09114facefa8ab1c6336f198c 100644 --- a/src/cmd/webui/project/mod.rs +++ b/src/cmd/webui/project/mod.rs @@ -284,6 +284,7 @@ fn build_section( priority: t.priority.as_str().to_string(), effort: t.effort.as_str().to_string(), title: t.title.clone(), + labels: t.labels.clone(), created_at_display: friendly_date(&t.created_at), created_at: t.created_at.clone(), } @@ -393,6 +394,12 @@ pub(in crate::cmd::webui) async fn project_handler( 5, ); + // Build a lookup from task ID to labels for the Next Up display. + let labels_by_id: std::collections::HashMap<&str, &[String]> = tasks + .iter() + .map(|t| (t.id.as_str(), t.labels.as_slice())) + .collect(); + let next_up: Vec = scored .into_iter() .map(|s| { @@ -415,6 +422,10 @@ pub(in crate::cmd::webui) async fn project_handler( "Unblocks: {} {} ({} directly)", s.total_unblocked, task_word, s.direct_unblocked ); + let labels = labels_by_id + .get(s.id.as_str()) + .map(|ls| ls.to_vec()) + .unwrap_or_default(); ScoredEntry { short_id: TaskId::display_id(&s.id), id: s.id, @@ -424,6 +435,7 @@ pub(in crate::cmd::webui) async fn project_handler( status_display: friendly_status("open"), equation, unblocks_display, + labels, } }) .collect(); diff --git a/src/cmd/webui/project/views.rs b/src/cmd/webui/project/views.rs index f8b1c9bc8ed027ef02ead43c5a9054c49a314f5c..5ffd7d4fffc051610e3d38f69f496fe342bc9cbf 100644 --- a/src/cmd/webui/project/views.rs +++ b/src/cmd/webui/project/views.rs @@ -14,6 +14,7 @@ pub(in crate::cmd::webui) struct ScoredEntry { pub(in crate::cmd::webui) equation: String, /// Human-friendly unblocks summary for the score tooltip. pub(in crate::cmd::webui) unblocks_display: String, + pub(in crate::cmd::webui) labels: Vec, } /// Minimal view-model for a task row in the project task table. @@ -26,6 +27,7 @@ pub(in crate::cmd::webui) struct TaskRow { pub(in crate::cmd::webui) priority: String, pub(in crate::cmd::webui) effort: String, pub(in crate::cmd::webui) title: String, + pub(in crate::cmd::webui) labels: Vec, pub(in crate::cmd::webui) created_at: String, pub(in crate::cmd::webui) created_at_display: String, } diff --git a/src/cmd/webui/task/mod.rs b/src/cmd/webui/task/mod.rs index f2c08f8c1dde850de789d346d46dd75664b42ffe..21cce8d7398ad1cee54e757043121840c9077b0d 100644 --- a/src/cmd/webui/task/mod.rs +++ b/src/cmd/webui/task/mod.rs @@ -62,6 +62,7 @@ pub(in crate::cmd::webui) async fn task_handler( priority: t.priority.as_str().to_string(), effort: t.effort.as_str().to_string(), title: t.title.clone(), + labels: t.labels.clone(), created_at_display: friendly_date(&t.created_at), created_at: t.created_at.clone(), } diff --git a/templates/macros.html b/templates/macros.html index 48541078c480e0de6eb1771321e4a4d1e22f0ced..695bffc1954f9a7fdc6a213a84392be5d1b0c237 100644 --- a/templates/macros.html +++ b/templates/macros.html @@ -68,6 +68,7 @@ Priority{{ section.sort_ctx.arrow("priority") }} Effort{{ section.sort_ctx.arrow("effort") }} Title{{ section.sort_ctx.arrow("title") }} + Labels Created{{ section.sort_ctx.arrow("created") }} Change status @@ -80,6 +81,7 @@ {{ t.priority }} {{ t.effort }} {{ t.title }} + {% for l in t.labels %}{% if !loop.first %}, {% endif %}{{ l }}{% endfor %} diff --git a/templates/project.html b/templates/project.html index 826833e7c098d32bfb86fa9ab33280d89453cd68..bc4e56599bbcb01d50992161511569d77a15162c 100644 --- a/templates/project.html +++ b/templates/project.html @@ -74,6 +74,7 @@ ID Score Title + Labels Change status @@ -84,6 +85,7 @@ {{ s.short_id }} {{ s.score }} {{ s.title }} + {% for l in s.labels %}{% if !loop.first %}, {% endif %}{{ l }}{% endfor %}