feat: migrate card position and due date
closes kemitix/trello-to-deck#10
This commit is contained in:
parent
738d7332d2
commit
61f4a36721
11 changed files with 61 additions and 13 deletions
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Reference in a new issue