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.
92 lines
2.7 KiB
Rust
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(())
|
|
}
|