feat(core): add move_task and rename_list to onyx-core
Add TaskRepository::move_task() to move tasks between lists and rename_list() to rename lists on the filesystem. Adds rename_list to the Storage trait with FileSystemStorage implementation. Includes tests for both operations plus duplicate-name error case. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6959b1f44f
commit
c4c03679ae
|
|
@ -68,6 +68,17 @@ impl TaskRepository {
|
|||
self.storage.delete_list(list_id)
|
||||
}
|
||||
|
||||
pub fn rename_list(&mut self, list_id: Uuid, new_name: String) -> Result<()> {
|
||||
self.storage.rename_list(list_id, new_name)
|
||||
}
|
||||
|
||||
pub fn move_task(&mut self, from_list_id: Uuid, to_list_id: Uuid, task_id: Uuid) -> Result<()> {
|
||||
let task = self.storage.read_task(from_list_id, task_id)?;
|
||||
self.storage.write_task(to_list_id, &task)?;
|
||||
self.storage.delete_task(from_list_id, task_id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Task ordering
|
||||
pub fn reorder_task(&mut self, list_id: Uuid, task_id: Uuid, new_position: usize) -> Result<()> {
|
||||
let mut metadata = self.storage.read_list_metadata(list_id)?;
|
||||
|
|
@ -320,6 +331,54 @@ mod tests {
|
|||
assert!(lists.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_move_task_between_lists() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let mut repo = TaskRepository::init(temp_dir.path().to_path_buf()).unwrap();
|
||||
|
||||
let list_a = repo.create_list("List A".to_string()).unwrap();
|
||||
let list_b = repo.create_list("List B".to_string()).unwrap();
|
||||
let task = repo.create_task(list_a.id, Task::new("Movable".to_string())).unwrap();
|
||||
|
||||
repo.move_task(list_a.id, list_b.id, task.id).unwrap();
|
||||
|
||||
let tasks_a = repo.list_tasks(list_a.id).unwrap();
|
||||
assert_eq!(tasks_a.len(), 0);
|
||||
|
||||
let tasks_b = repo.list_tasks(list_b.id).unwrap();
|
||||
assert_eq!(tasks_b.len(), 1);
|
||||
assert_eq!(tasks_b[0].title, "Movable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_list() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let mut repo = TaskRepository::init(temp_dir.path().to_path_buf()).unwrap();
|
||||
|
||||
let list = repo.create_list("Old Name".to_string()).unwrap();
|
||||
repo.rename_list(list.id, "New Name".to_string()).unwrap();
|
||||
|
||||
let renamed = repo.get_list(list.id).unwrap();
|
||||
assert_eq!(renamed.title, "New Name");
|
||||
|
||||
// Old directory should be gone
|
||||
assert!(!temp_dir.path().join("Old Name").exists());
|
||||
assert!(temp_dir.path().join("New Name").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_list_duplicate_name() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let mut repo = TaskRepository::init(temp_dir.path().to_path_buf()).unwrap();
|
||||
|
||||
repo.create_list("A".to_string()).unwrap();
|
||||
let list_b = repo.create_list("B".to_string()).unwrap();
|
||||
|
||||
let result = repo.rename_list(list_b.id, "A".to_string());
|
||||
assert!(result.is_err());
|
||||
assert!(matches!(result.unwrap_err(), Error::InvalidData(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_list_removes_from_root_metadata() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ pub trait Storage {
|
|||
fn read_root_metadata(&self) -> Result<RootMetadata>;
|
||||
fn write_root_metadata(&mut self, metadata: &RootMetadata) -> Result<()>;
|
||||
|
||||
fn rename_list(&mut self, list_id: Uuid, new_name: String) -> Result<()>;
|
||||
|
||||
fn read_list_metadata(&self, list_id: Uuid) -> Result<ListMetadata>;
|
||||
fn write_list_metadata(&mut self, metadata: &ListMetadata) -> Result<()>;
|
||||
}
|
||||
|
|
@ -464,6 +466,27 @@ impl Storage for FileSystemStorage {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn rename_list(&mut self, list_id: Uuid, new_name: String) -> Result<()> {
|
||||
let old_dir = self.list_dir_path(list_id)?;
|
||||
let new_dir = self.list_dir_path_by_name(&new_name);
|
||||
|
||||
if new_dir.exists() {
|
||||
return Err(Error::InvalidData(format!("A list named '{}' already exists", new_name)));
|
||||
}
|
||||
|
||||
fs::rename(&old_dir, &new_dir)?;
|
||||
|
||||
// Update metadata timestamp
|
||||
let metadata_path = new_dir.join(".listdata.json");
|
||||
let content = fs::read_to_string(&metadata_path)?;
|
||||
let mut metadata: ListMetadata = serde_json::from_str(&content)?;
|
||||
metadata.updated_at = Utc::now();
|
||||
let json = serde_json::to_string_pretty(&metadata)?;
|
||||
fs::write(&metadata_path, json)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_root_metadata(&self) -> Result<RootMetadata> {
|
||||
self.read_root_metadata_internal()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue