onyx-tasks/crates/onyx-cli/src/commands/list.rs
Tristan Michael 9ed84690ac Rename due_date to date across codebase
The kebab menu and docs referred to a task "due date" but the field was
just a date; this change renames due_date/group_by_due_date and related
identifiers to date/group_by_date across Rust, TypeScript, Svelte, CLI,
docs and tests to keep terminology consistent. Updates include
API/command names, storage/models, repository methods, UI text, JS
variables and builder/parse functions so code, tests and documentation
all use "date" semantics.
Preserve old "group_by_due_date" field name

Add serde alias to ListMetadata.group_by_date so older .listdata.json
files that used the previous field name (group_by_due_date) can still be
deserialized correctly. This fixes serialization/deserialization issues
encountered at /home/trztn/Documents/Onyx and
/var/home/trztn/Nextcloud/Onyx.
the frontmatter due should be date... I don't want due anywhere

- Renamed `TaskFrontmatter.due` → `TaskFrontmatter.date`; YAML key on disk is now `date:` instead of `due:`
- Added `#[serde(alias = "due")]` so existing task files with `due:` frontmatter still deserialize correctly
- Updated google_tasks.rs to write `date:` instead of `due:` in generated YAML
- Renamed CLI `--due` flag to `--date`; updated function signature and display string "Due:" → "Date:"
Remove serde aliases and rename due→date

Drop backwards-compat aliases and update frontmatter/metadata to use the
canonical "date"/"group_by_date" fields. The aliases for
group_by_due_date and due were removed to avoid maintaining
backward-compatibility and to reflect the current schema. Updated
storage types to rename the fields and adjusted serialization attributes
so YAML/JSON frontmatter and .listdata.json files now use group_by_date
and date consistently.
2026-04-14 07:36:10 -07:00

92 lines
2.7 KiB
Rust

use anyhow::{Context, Result};
use colored::*;
use onyx_core::{Task, TaskStatus};
use crate::output;
use crate::commands::get_repository;
fn print_tasks(tasks: &[Task]) {
if tasks.is_empty() {
output::item("No tasks");
return;
}
for task in tasks {
let checkbox = if task.status == TaskStatus::Completed { "[✓]".green() } else { "[ ]".normal() };
let due_str = task.date.map(|d| format!(" ({})", d.format("%Y-%m-%d")).yellow().to_string()).unwrap_or_default();
output::item(&format!("{} {}{} {}", checkbox, task.title, due_str, task.id.to_string().dimmed()));
}
}
pub fn create(name: String, workspace: Option<String>) -> Result<()> {
let (mut repo, _workspace_name) = get_repository(workspace)?;
repo.create_list(name.clone())
.context("Failed to create list")?;
output::success(&format!("Created list \"{}\"", name));
Ok(())
}
pub fn show(list_name: Option<String>, workspace: Option<String>) -> Result<()> {
let (repo, _workspace_name) = get_repository(workspace)?;
let lists = repo.get_lists()
.context("Failed to get lists")?;
if lists.is_empty() {
output::info("No lists found. Create one with 'onyx list create <name>'");
return Ok(());
}
// If a specific list is requested, show only that one
if let Some(name) = list_name {
let list = lists.iter()
.find(|l| l.title == name)
.ok_or_else(|| anyhow::anyhow!("List '{}' not found", name))?;
output::header(&format!("{} ({})", list.title, format!("{} tasks", list.tasks.len()).dimmed()));
print_tasks(&list.tasks);
} else {
// Show all lists
for list in &lists {
output::header(&format!("{} ({})", list.title, format!("{} tasks", list.tasks.len()).dimmed()));
print_tasks(&list.tasks);
output::blank();
}
}
Ok(())
}
pub fn delete(name: String, workspace: Option<String>) -> Result<()> {
let (mut repo, _workspace_name) = get_repository(workspace)?;
let lists = repo.get_lists()
.context("Failed to get lists")?;
let list = lists.iter()
.find(|l| l.title == name)
.ok_or_else(|| anyhow::anyhow!("List '{}' not found", name))?;
// Confirm
output::warning(&format!("This will delete list \"{}\" and all its tasks", name));
print!("Continue? (y/n): ");
use std::io::{self, Write};
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if input.trim().to_lowercase() != "y" {
output::info("Cancelled");
return Ok(());
}
repo.delete_list(list.id)
.context("Failed to delete list")?;
output::success(&format!("Deleted list \"{}\"", name));
Ok(())
}