diff --git a/src/check.rs b/src/check.rs new file mode 100644 index 0000000..aa6619f --- /dev/null +++ b/src/check.rs @@ -0,0 +1,44 @@ +// +use color_eyre::eyre::{OptionExt as _, Result}; + +use crate::{f, p, trello::api::boards::TrelloBoards as _, FullCtx}; + +pub(crate) async fn run(ctx: FullCtx) -> Result<()> { + // test trello by getting a list of the boards for the user + p!(ctx.prt, ">> Testing Trello details..."); + let boards = crate::trello::api::members::get_boards_that_member_belongs_to( + &ctx.cfg.trello, + &ctx.net, + &ctx.prt, + ) + .await + .result?; + p!(ctx.prt, "<<< Trello Credentials: OKAY"); + let board_name = &ctx.cfg.trello.board_name; + p!(ctx.prt, ">> Trello Board: {board_name}"); + let board = boards + .find_by_name(board_name) + .ok_or_eyre(f!("board not found: {board_name}"))?; + p!(ctx.prt, "<<< Trello Board: OKAY"); + for list in &board.lists { + p!(ctx.prt, "<<< List: {}", list.name); + } + + p!(ctx.prt, ">> Testing Nextcloud details..."); + let deck_client = ctx.deck_client(); + let board = deck_client + .get_board(ctx.cfg.nextcloud.board_id) + .await + .result?; + p!(ctx.prt, "<<< Nextcloud Credentials: OKAY"); + p!(ctx.prt, "<<< Nextcloud Board: {}", board.title); + let stacks = deck_client + .get_stacks(ctx.cfg.nextcloud.board_id) + .await + .result?; + for stack in stacks { + p!(ctx.prt, "<<< Stack: {}", stack.title); + } + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 2862005..a51023c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub use config::AppConfig; use kxio::{fs::FileSystem, net::Net, print::Printer}; mod api_result; +mod check; mod config; mod init; mod macros; @@ -141,7 +142,7 @@ pub async fn run(ctx: Ctx) -> color_eyre::Result<()> { }; match commands.command { Command::Init => Err(eyre!("Config file already exists. Not overwriting it.")), - Command::Check => todo!("check"), + Command::Check => check::run(ctx).await, Command::Import => todo!("import"), Command::Trello(TrelloCommand::Board(TrelloBoardCommand::List { dump })) => { trello::boards::list(ctx, dump).await diff --git a/src/nextcloud/model.rs b/src/nextcloud/model.rs index de58143..0367a00 100644 --- a/src/nextcloud/model.rs +++ b/src/nextcloud/model.rs @@ -112,7 +112,7 @@ newtype!( "Title of the Card" ); -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct NextcloudBoardOwner { #[serde(rename = "primaryKey")] pub primary_key: String, @@ -121,7 +121,7 @@ pub struct NextcloudBoardOwner { pub display_name: String, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Board { pub id: NextcloudBoardId, pub title: NextcloudBoardTitle, @@ -157,7 +157,7 @@ pub struct Card { #[serde(default)] pub due_date: Option, #[serde(default)] - pub labels: Option>, + pub labels: Option>, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/nextcloud/tests.rs b/src/nextcloud/tests.rs index b7cfdd3..7daa5aa 100644 --- a/src/nextcloud/tests.rs +++ b/src/nextcloud/tests.rs @@ -149,6 +149,33 @@ mod commands { mod stack { use super::*; + #[tokio::test] + async fn get_stack_parse() { + //given + let mock_net = kxio::net::mock(); + + mock_net + .on() + .get("https://host-name/index.php/apps/deck/api/v1.0/boards/2/stacks") + .basic_auth("username", Some("password")) + .respond(StatusCode::OK) + .body(include_str!( + "../tests/responses/nextcloud-stack-list-2.json" + )) + .expect("mock request"); + + let fs = given::a_filesystem(); + let ctx = given::a_full_context(mock_net, fs); + let deck_client = DeckClient::new(&ctx); + + //when + let result = deck_client + .get_stacks(ctx.cfg.nextcloud.board_id) + .await + .result; + assert!(result.is_ok()); + } + #[tokio::test] async fn list() { //given diff --git a/src/tests/mod.rs b/src/tests/mod.rs index f7746e8..aba732e 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -132,7 +132,6 @@ mod given { pub fn a_context(fs: FileSystem, net: Net, prt: Printer) -> Ctx { Ctx { fs, net, prt } } - pub fn a_filesystem() -> TempFileSystem { kxio::fs::temp().expect("temp fs") } diff --git a/src/tests/responses/nextcloud-stack-list-2.json b/src/tests/responses/nextcloud-stack-list-2.json new file mode 100644 index 0000000..c576c6c --- /dev/null +++ b/src/tests/responses/nextcloud-stack-list-2.json @@ -0,0 +1,263 @@ +[ + { + "id": 1, + "title": "To do", + "boardId": 1, + "deletedAt": 0, + "lastModified": 1733515897, + "cards": [ + { + "id": 318, + "title": "This", + "description": "", + "stackId": 1, + "type": "plain", + "lastModified": 1733049748, + "lastEditor": null, + "createdAt": 1732610548, + "labels": [], + "assignedUsers": [], + "attachments": null, + "attachmentCount": 1, + "owner": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "order": 0, + "archived": false, + "done": null, + "duedate": null, + "deletedAt": 0, + "commentsUnread": 0, + "commentsCount": 0, + "ETag": "e5007451d88799e3e3d3581cbcb30210", + "overdue": 0 + }, + { + "id": 321, + "title": "Breakfast: Cereal", + "description": "", + "stackId": 1, + "type": "plain", + "lastModified": 1733515897, + "lastEditor": null, + "createdAt": 1733043461, + "labels": [ + { + "id": 1, + "title": "Finished", + "color": "31CC7C", + "boardId": 1, + "cardId": 321, + "lastModified": 1670965629, + "ETag": "983f87848dc9c18d0aee63e7ee0fc83f" + }, + { + "id": 2, + "title": "To review", + "color": "317CCC", + "boardId": 1, + "cardId": 321, + "lastModified": 1670965629, + "ETag": "983f87848dc9c18d0aee63e7ee0fc83f" + }, + { + "id": 3, + "title": "Action needed", + "color": "FF7A66", + "boardId": 1, + "cardId": 321, + "lastModified": 1670965629, + "ETag": "983f87848dc9c18d0aee63e7ee0fc83f" + }, + { + "id": 4, + "title": "Later", + "color": "F1DB50", + "boardId": 1, + "cardId": 321, + "lastModified": 1670965629, + "ETag": "983f87848dc9c18d0aee63e7ee0fc83f" + } + ], + "assignedUsers": [ + { + "id": 24, + "participant": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "cardId": 321, + "type": 0 + } + ], + "attachments": null, + "attachmentCount": 0, + "owner": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "order": 1, + "archived": false, + "done": null, + "duedate": null, + "deletedAt": 0, + "commentsUnread": 0, + "commentsCount": 0, + "ETag": "bf59162abcbc193b94349985122d7009", + "overdue": 0 + } + ], + "order": 0, + "ETag": "bf59162abcbc193b94349985122d7009" + }, + { + "id": 3, + "title": "Done", + "boardId": 1, + "deletedAt": 0, + "lastModified": 1733515991, + "cards": [ + { + "id": 322, + "title": "Lunch: Soup & Toast", + "description": "", + "stackId": 3, + "type": "plain", + "lastModified": 1733515991, + "lastEditor": null, + "createdAt": 1733043472, + "labels": [ + { + "id": 4, + "title": "Later", + "color": "F1DB50", + "boardId": 1, + "cardId": 322, + "lastModified": 1670965629, + "ETag": "983f87848dc9c18d0aee63e7ee0fc83f" + } + ], + "assignedUsers": [ + { + "id": 25, + "participant": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "cardId": 322, + "type": 0 + } + ], + "attachments": null, + "attachmentCount": 0, + "owner": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "order": 0, + "archived": false, + "done": null, + "duedate": null, + "deletedAt": 0, + "commentsUnread": 0, + "commentsCount": 0, + "ETag": "dda386b3b247d7b4bd8917e19d38c01b", + "overdue": 0 + } + ], + "order": 2, + "ETag": "dda386b3b247d7b4bd8917e19d38c01b" + }, + { + "id": 2, + "title": "Doing", + "boardId": 1, + "deletedAt": 0, + "lastModified": 1733337420, + "cards": [ + { + "id": 319, + "title": "That", + "description": "", + "stackId": 2, + "type": "plain", + "lastModified": 1733335979, + "lastEditor": null, + "createdAt": 1732610551, + "labels": [], + "assignedUsers": [], + "attachments": null, + "attachmentCount": 1, + "owner": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "order": 0, + "archived": false, + "done": null, + "duedate": null, + "deletedAt": 0, + "commentsUnread": 0, + "commentsCount": 0, + "ETag": "79aeb703494e67736cc66b35053d258d", + "overdue": 0 + }, + { + "id": 323, + "title": "Second lunch: Poached Egg & Toasted Muffin", + "description": "", + "stackId": 2, + "type": "plain", + "lastModified": 1733337420, + "lastEditor": null, + "createdAt": 1733043481, + "labels": [], + "assignedUsers": [ + { + "id": 26, + "participant": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "cardId": 323, + "type": 0 + } + ], + "attachments": null, + "attachmentCount": 0, + "owner": { + "primaryKey": "pcampbell", + "uid": "pcampbell", + "displayname": "Paul Campbell", + "type": 0 + }, + "order": 1, + "archived": false, + "done": null, + "duedate": null, + "deletedAt": 0, + "commentsUnread": 0, + "commentsCount": 0, + "ETag": "3da05f904903c88450b79e4f8f6e2160", + "overdue": 0 + } + ], + "order": 1, + "ETag": "3da05f904903c88450b79e4f8f6e2160" + } +] \ No newline at end of file diff --git a/src/tests/responses/trello-boards.json b/src/tests/responses/trello-boards.json new file mode 100644 index 0000000..5d17d40 --- /dev/null +++ b/src/tests/responses/trello-boards.json @@ -0,0 +1,69 @@ +[ + { + "id": "5abbe4b7ddc1b351ef961414", + "name": "Trello Platform Changes", + "desc": "Track changes to Trello's Platform on this board.", + "descData": "", + "closed": false, + "idMemberCreator": "5abbe4b7ddc1b351ef961414", + "idOrganization": "5abbe4b7ddc1b351ef961414", + "pinned": false, + "url": "https://trello.com/b/dQHqCohZ/trello-platform-changelog", + "shortUrl": "https://trello.com/b/dQHqCohZ", + "prefs": { + "permissionLevel": "org", + "hideVotes": true, + "voting": "disabled", + "comments": "", + "selfJoin": true, + "cardCovers": true, + "isTemplate": true, + "cardAging": "pirate", + "calendarFeedEnabled": true, + "background": "5abbe4b7ddc1b351ef961414", + "backgroundImage": "", + "backgroundImageScaled": [ + {} + ], + "backgroundTile": true, + "backgroundBrightness": "dark", + "backgroundBottomColor": "#1e2e00", + "backgroundTopColor": "#ffffff", + "canBePublic": true, + "canBeEnterprise": true, + "canBeOrg": true, + "canBePrivate": true, + "canInvite": true + }, + "labelNames": { + "green": "Addition", + "yellow": "Update", + "orange": "Deprecation", + "red": "Deletion", + "purple": "Power-Ups", + "blue": "News", + "sky": "Announcement", + "lime": "Delight", + "pink": "REST API", + "black": "Capabilties" + }, + "limits": { + "attachments": { + "perBoard": {} + } + }, + "starred": true, + "memberships": "", + "shortLink": "", + "subscribed": true, + "powerUps": "", + "dateLastActivity": "", + "dateLastView": "", + "idTags": "", + "datePluginDisable": "", + "creationMethod": "", + "ixUpdate": 2154, + "templateGallery": "", + "enterpriseOwned": true + } +] diff --git a/src/trello/api/boards.rs b/src/trello/api/boards.rs index 4056ede..d3f18c6 100644 --- a/src/trello/api/boards.rs +++ b/src/trello/api/boards.rs @@ -1,17 +1,9 @@ // -// use crate::trello::types::board::TrelloBoard; // use color_eyre::Result; // use kxio::net::Net; -// -// use crate::{ -// f, -// trello::{ -// types::{TrelloAuth, TrelloBoardId}, -// url, -// }, -// }; -// use crate::trello::types::TrelloBoardName; + +use crate::trello::types::{board::TrelloBoard, TrelloBoardName}; // pub async fn get_board( // auth: &TrelloAuth, @@ -31,11 +23,11 @@ // Ok(board) // } -// pub trait TrelloBoards { -// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard>; -// } -// impl TrelloBoards for Vec { -// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard> { -// self.iter().find(|b| &b.name == board_name) -// } -// } +pub trait TrelloBoards { + fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard>; +} +impl TrelloBoards for Vec { + fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard> { + self.iter().find(|b| &b.name == board_name) + } +} diff --git a/src/trello/types/auth.rs b/src/trello/types/auth.rs index cbb3ce4..d93af34 100644 --- a/src/trello/types/auth.rs +++ b/src/trello/types/auth.rs @@ -27,13 +27,13 @@ impl<'cfg> TrelloAuth<'cfg> { } pub const fn api_key(&self) -> &TrelloApiKey { - &self.api_key + self.api_key } pub const fn api_token(&self) -> &TrelloApiSecret { - &self.api_secret + self.api_secret } } -impl<'cfg> From> for HashMap { +impl From> for HashMap { fn from(value: TrelloAuth) -> Self { HashMap::from([( "Authorization".into(),