From 22bb06c151825bb78a66114047ada0ec50e05fc8 Mon Sep 17 00:00:00 2001 From: ToBinio Date: Wed, 6 May 2026 10:18:17 +0200 Subject: [PATCH] handle tags while updating --- api/src/services/todos.rs | 52 ++++++++++++++++++++++++++++----------- api/tests/todos/update.rs | 21 ++++++++++++++++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/api/src/services/todos.rs b/api/src/services/todos.rs index 4349079..f7692b3 100644 --- a/api/src/services/todos.rs +++ b/api/src/services/todos.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use chrono::{Local, NaiveDate}; use migration::Expr; @@ -171,26 +171,50 @@ impl TodoService { db: &DatabaseConnection, todo: TodoModel, ) -> Result { - Todo::update(todo::ActiveModel { + let updated = Todo::update(todo::ActiveModel { id: Set(todo.uuid), owner_id: Set(user.uuid), - title: Set(todo.title), - note: Set(todo.note), + title: Set(todo.title.clone()), + note: Set(todo.note.clone()), category_id: Set(todo.category), order: NotSet, }) .filter(todo::Column::OwnerId.eq(user.uuid)) .exec(db) - .await - .map(|todo| TodoModel { - uuid: todo.id, - title: todo.title, - note: todo.note, - time: None, - tags: vec![], - category: None, - checks: vec![], - }) + .await?; + + let incoming: HashSet<_> = todo.tags.iter().cloned().collect(); + let existing: HashSet<_> = TodoTag::find() + .filter(todo_tag::Column::TodoId.eq(todo.uuid)) + .all(db) + .await? + .into_iter() + .map(|t| t.tag_id) + .collect(); + + let to_insert: Vec<_> = incoming.difference(&existing).cloned().collect(); + let to_delete: Vec<_> = existing.difference(&incoming).cloned().collect(); + + if !to_delete.is_empty() { + TodoTag::delete_many() + .filter(todo_tag::Column::TodoId.eq(todo.uuid)) + .filter(todo_tag::Column::TagId.is_in(to_delete)) + .exec(db) + .await?; + } + + if !to_insert.is_empty() { + TodoTag::insert_many(to_insert.into_iter().map(|tag_id| todo_tag::ActiveModel { + todo_id: Set(todo.uuid), + tag_id: Set(tag_id), + })) + .exec(db) + .await?; + } + + Self::get_by_id(user, db, updated.id) + .await + .map(|todo| todo.unwrap()) } pub async fn delete_by_id( diff --git a/api/tests/todos/update.rs b/api/tests/todos/update.rs index 37710e3..9b79d78 100644 --- a/api/tests/todos/update.rs +++ b/api/tests/todos/update.rs @@ -13,6 +13,27 @@ async fn update_todos() { let tag_uuid = Uuid::new_v4(); let category_uuid = Uuid::new_v4(); + client + .add_category_json(json!( + { + "uuid": category_uuid, + "name": "Test Category", + "color": "#233212", + "icon": "icon", + } + )) + .await; + + client + .add_tag_json(json!( + { + "uuid": tag_uuid, + "name": "Test Tag", + "color": "#233212", + } + )) + .await; + client .add_todo_json(json!( { -- 2.51.2