feat: migrate card position and due date
Some checks failed
Test / build (map[name:stable]) (push) Successful in 4m51s
Test / build (map[name:nightly]) (push) Successful in 3m42s
Release Please / Release-plz (push) Failing after 35s

closes kemitix/trello-to-deck#10
This commit is contained in:
Paul Campbell 2024-12-31 11:40:56 +00:00
parent 738d7332d2
commit 61f4a36721
11 changed files with 61 additions and 13 deletions

View file

@ -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())
}
}

View file

@ -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<NextcloudCardDescription> = 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

View file

@ -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(),
)

View file

@ -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<String>,
#[clap(long)]
due: Option<String>,
},
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 {

View file

@ -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<Card> {
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,

View file

@ -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 {

View file

@ -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<String>,
#[case] due: Option<String>,
) {
//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<String>,
#[case] due: Option<String>,
) {
//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

View file

@ -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,

View file

@ -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",

View file

@ -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",

View file

@ -39,6 +39,7 @@ pub(crate) struct TrelloShortCard {
pub(crate) desc: TrelloCardDescription,
pub(crate) labels: Vec<TrelloLabel>,
pub(crate) pos: TrelloCardPosition,
pub(crate) due: Option<TrelloCardDue>,
}
#[derive(Debug, PartialEq, Eq, Deserialize)]