diff --git a/src/conversion.rs b/src/conversion.rs index 3b04bb5..63710e4 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -1,5 +1,6 @@ // -use crate::nextcloud::model::NextcloudStackTitle; +use crate::nextcloud::model::{NextcloudDueDate, NextcloudStackTitle}; +use crate::trello::model::card::TrelloCardDue; use crate::{ nextcloud::model::{NextcloudCardDescription, NextcloudCardTitle, NextcloudOrder}, trello::model::{ @@ -37,3 +38,9 @@ impl From<&TrelloCardPosition> for NextcloudOrder { Self::new(value.0) } } + +impl From<&TrelloCardDue> for NextcloudDueDate { + fn from(value: &TrelloCardDue) -> Self { + Self::new(value.to_string()) + } +} diff --git a/src/import/card.rs b/src/import/card.rs index 202dd40..5055c51 100644 --- a/src/import/card.rs +++ b/src/import/card.rs @@ -8,6 +8,7 @@ use kameo::{ Actor, }; +use crate::nextcloud::model::{NextcloudDueDate, NextcloudOrder}; use crate::{ ask, import::{ @@ -69,10 +70,12 @@ impl Actor for ImportCardActor { tracing::info!(name = %this.trello_card.name, "importing card"); // - - create a nextcloud card let title = NextcloudCardTitle::from(&this.trello_card.name); + let order = NextcloudOrder::from(&this.trello_card.pos); let desc: Option = match this.trello_card.desc.len() { 0 => None, _ => Some(NextcloudCardDescription::from(&this.trello_card.desc)), }; + let due_date = this.trello_card.due.as_ref().map(NextcloudDueDate::from); tracing::info!("Nextcloud: Create card"); let nextcloud_card_id = match this @@ -82,7 +85,9 @@ impl Actor for ImportCardActor { this.nextcloud_board_id, this.nextcloud_stack_id, &title, + &order, desc.as_ref(), + due_date.as_ref(), ) .await .result diff --git a/src/import/tests/mod.rs b/src/import/tests/mod.rs index 802a63e..ec4ff91 100644 --- a/src/import/tests/mod.rs +++ b/src/import/tests/mod.rs @@ -61,6 +61,7 @@ fn trello_card_without_description_or_label() -> TrelloShortCard { desc: s!("").into(), labels: vec![], pos: 333.into(), + due: Some(s!("2025-01-07T00:00:00.000Z").into()), } } @@ -316,8 +317,11 @@ fn given_nextcloud_create_card_with_description(mock_net: &MockNet) { .body( json!({ "description": "A list of the things we think we want to do, maybe not quite ready for work, but high likelihood of being worked on.\n\nThis is the staging area where specs should get fleshed out.\n\nNo limit on the list size, but we should reconsider if it gets long.", + "duedate": "2025-01-07T00:00:00.000Z", + "order": 16384, "title": "Backlog", - }) // TODO: (#10) include card 'order' from trello 'pos' + "type":"plain" + }) .to_string(), ) .respond(StatusCode::OK) @@ -333,7 +337,9 @@ fn given_nextcloud_create_card_without_description(mock_net: &MockNet) { .body( json!({ // "description": "trello-desc", + "order": 16384, "title": "Backlog", + "type":"plain" }) // TODO: (#10) include card 'order' from trello 'pos' .to_string(), ) diff --git a/src/nextcloud/card.rs b/src/nextcloud/card.rs index 25a1191..045e5f9 100644 --- a/src/nextcloud/card.rs +++ b/src/nextcloud/card.rs @@ -3,8 +3,13 @@ use std::path::PathBuf; use clap::Parser; -use crate::nextcloud::model::{NextcloudCardDescription, NextcloudCardTitle}; -use crate::{execute::Execute, p, FullCtx}; +use crate::{ + execute::Execute, + nextcloud::model::{ + NextcloudCardDescription, NextcloudCardTitle, NextcloudDueDate, NextcloudOrder, + }, + p, FullCtx, +}; #[derive(Parser, Debug)] pub enum NextcloudCardCommand { @@ -23,7 +28,11 @@ pub enum NextcloudCardCommand { #[clap(long)] title: String, #[clap(long)] + order: i64, + #[clap(long)] description: Option, + #[clap(long)] + due: Option, }, AddLabel { #[clap(long, action = clap::ArgAction::SetTrue)] @@ -76,7 +85,9 @@ impl Execute for NextcloudCardCommand { board_id, stack_id, title, + order, description, + due, } => { let api_result = ctx .deck_client() @@ -84,10 +95,12 @@ impl Execute for NextcloudCardCommand { (*board_id).into(), (*stack_id).into(), &NextcloudCardTitle::new(title), + &NextcloudOrder::new(*order), description .as_ref() .map(NextcloudCardDescription::new) .as_ref(), + due.as_ref().map(NextcloudDueDate::new).as_ref(), ) .await; if *dump { diff --git a/src/nextcloud/client.rs b/src/nextcloud/client.rs index 479e579..285b4a8 100644 --- a/src/nextcloud/client.rs +++ b/src/nextcloud/client.rs @@ -8,7 +8,7 @@ use reqwest::multipart; use serde_json::{json, Value}; use tracing::instrument; -use crate::nextcloud::model::NextcloudOrder; +use crate::nextcloud::model::{NextcloudDueDate, NextcloudOrder}; use crate::{ api_result::APIResult, f, @@ -149,16 +149,25 @@ impl<'ctx> DeckClient<'ctx> { board_id: NextcloudBoardId, stack_id: NextcloudStackId, title: &NextcloudCardTitle, + order: &NextcloudOrder, description: Option<&NextcloudCardDescription>, + due_date: Option<&NextcloudDueDate>, ) -> APIResult { let mut body = json!({ "title": title, + "type": "plain", + "order": order, }); if let Some(desc) = &description { - body["description"] = serde_json::Value::String(desc.to_string()); + body["description"] = Value::String(desc.to_string()); } + if let Some(due_date) = &due_date { + body["duedate"] = Value::String(due_date.to_string()); + } + + tracing::info!(body = %body.to_string()); self.request_with_body( f!("boards/{board_id}/stacks/{stack_id}/cards"), body, diff --git a/src/nextcloud/model.rs b/src/nextcloud/model.rs index 3c9a8e6..b14f2e5 100644 --- a/src/nextcloud/model.rs +++ b/src/nextcloud/model.rs @@ -139,6 +139,7 @@ newtype!( Ord, "Description of the Card" ); +newtype!(NextcloudDueDate, String, "Due date of the Card"); #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub(crate) struct Board { diff --git a/src/nextcloud/tests/card/create.rs b/src/nextcloud/tests/card/create.rs index fbd1ef1..a867cce 100644 --- a/src/nextcloud/tests/card/create.rs +++ b/src/nextcloud/tests/card/create.rs @@ -43,14 +43,15 @@ fn ctx() -> FullCtx { } #[rstest::rstest] -#[case::no_desc(None)] -#[case::desc(Some(s!("my new description")))] +#[case::no_desc_or_due(None, None)] +#[case::desc_and_due(Some(s!("my new description")), Some(s!("2025-01-07T00:00:00.000Z")))] #[test_log::test(tokio::test)] async fn dump( ctx: FullCtx, board_id: NextcloudBoardId, stack_id: NextcloudStackId, #[case] description: Option, + #[case] due: Option, ) { //given let prt = ctx.prt.clone(); @@ -62,7 +63,9 @@ async fn dump( board_id: board_id.into(), stack_id: stack_id.into(), title: "my new card".to_string(), + order: 42, description, + due, })) .execute(&ctx) .await @@ -79,14 +82,15 @@ async fn dump( } #[rstest::rstest] -#[case::no_desc(None)] -#[case::desc(Some(s!("my new description")))] +#[case::no_desc_or_due(None, None)] +#[case::desc_and_due(Some(s!("my new description")), Some(s!("2025-01-07T00:00:00.000Z")))] #[test_log::test(tokio::test)] async fn no_dump( ctx: FullCtx, board_id: NextcloudBoardId, stack_id: NextcloudStackId, #[case] description: Option, + #[case] due: Option, ) { //given let prt = ctx.prt.clone(); @@ -98,7 +102,9 @@ async fn no_dump( board_id: board_id.into(), stack_id: stack_id.into(), title: "my new card".to_string(), + order: 42, description, + due, })) .execute(&ctx) .await diff --git a/src/tests/responses/nextcloud-card-create.json b/src/tests/responses/nextcloud-card-create.json index 1f4bb87..3b28178 100644 --- a/src/tests/responses/nextcloud-card-create.json +++ b/src/tests/responses/nextcloud-card-create.json @@ -17,7 +17,7 @@ "order": 999, "archived": false, "done": null, - "duedate": null, + "duedate": "2025-01-07T00:00:00.000Z", "notified": false, "deletedAt": 0, "commentsUnread": 0, diff --git a/src/tests/responses/trello-card-get.json b/src/tests/responses/trello-card-get.json index 3461c0b..868772d 100644 --- a/src/tests/responses/trello-card-get.json +++ b/src/tests/responses/trello-card-get.json @@ -31,7 +31,7 @@ "dateLastActivity": "2024-12-25T08:40:39.500Z", "desc": "A list of the things we think we want to do, maybe not quite ready for work, but high likelihood of being worked on.\n\nThis is the staging area where specs should get fleshed out.\n\nNo limit on the list size, but we should reconsider if it gets long.", "descData": null, - "due": null, + "due": "2025-01-07T00:00:00.000Z", "dueReminder": null, "email": null, "idBoard": "65ad94865aed24f70ecdce4b", diff --git a/src/tests/responses/trello-list-get.json b/src/tests/responses/trello-list-get.json index 159432d..a26d6a0 100644 --- a/src/tests/responses/trello-list-get.json +++ b/src/tests/responses/trello-list-get.json @@ -32,7 +32,7 @@ "dateLastActivity": "2024-01-21T22:02:47.582Z", "desc": "A list of the things we think we want to do, maybe not quite ready for work, but high likelihood of being worked on.\n\nThis is the staging area where specs should get fleshed out.\n\nNo limit on the list size, but we should reconsider if it gets long.", "descData": null, - "due": null, + "due": "2025-01-07T00:00:00.000Z", "dueReminder": null, "email": null, "idBoard": "65ad94865aed24f70ecdce4b", diff --git a/src/trello/model/card.rs b/src/trello/model/card.rs index d2442d8..4ce694e 100644 --- a/src/trello/model/card.rs +++ b/src/trello/model/card.rs @@ -39,6 +39,7 @@ pub(crate) struct TrelloShortCard { pub(crate) desc: TrelloCardDescription, pub(crate) labels: Vec, pub(crate) pos: TrelloCardPosition, + pub(crate) due: Option, } #[derive(Debug, PartialEq, Eq, Deserialize)]