feat: add command 'check'

This commit is contained in:
Paul Campbell 2024-11-29 14:31:40 +00:00
parent 13f34b3439
commit de9a378b3e
9 changed files with 421 additions and 26 deletions

44
src/check.rs Normal file
View file

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

View file

@ -7,6 +7,7 @@ pub use config::AppConfig;
use kxio::{fs::FileSystem, net::Net, print::Printer}; use kxio::{fs::FileSystem, net::Net, print::Printer};
mod api_result; mod api_result;
mod check;
mod config; mod config;
mod init; mod init;
mod macros; mod macros;
@ -141,7 +142,7 @@ pub async fn run(ctx: Ctx) -> color_eyre::Result<()> {
}; };
match commands.command { match commands.command {
Command::Init => Err(eyre!("Config file already exists. Not overwriting it.")), 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::Import => todo!("import"),
Command::Trello(TrelloCommand::Board(TrelloBoardCommand::List { dump })) => { Command::Trello(TrelloCommand::Board(TrelloBoardCommand::List { dump })) => {
trello::boards::list(ctx, dump).await trello::boards::list(ctx, dump).await

View file

@ -112,7 +112,7 @@ newtype!(
"Title of the Card" "Title of the Card"
); );
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub struct NextcloudBoardOwner { pub struct NextcloudBoardOwner {
#[serde(rename = "primaryKey")] #[serde(rename = "primaryKey")]
pub primary_key: String, pub primary_key: String,
@ -121,7 +121,7 @@ pub struct NextcloudBoardOwner {
pub display_name: String, 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 struct Board {
pub id: NextcloudBoardId, pub id: NextcloudBoardId,
pub title: NextcloudBoardTitle, pub title: NextcloudBoardTitle,
@ -157,7 +157,7 @@ pub struct Card {
#[serde(default)] #[serde(default)]
pub due_date: Option<String>, pub due_date: Option<String>,
#[serde(default)] #[serde(default)]
pub labels: Option<Vec<String>>, pub labels: Option<Vec<Label>>,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]

View file

@ -149,6 +149,33 @@ mod commands {
mod stack { mod stack {
use super::*; 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] #[tokio::test]
async fn list() { async fn list() {
//given //given

View file

@ -132,7 +132,6 @@ mod given {
pub fn a_context(fs: FileSystem, net: Net, prt: Printer) -> Ctx { pub fn a_context(fs: FileSystem, net: Net, prt: Printer) -> Ctx {
Ctx { fs, net, prt } Ctx { fs, net, prt }
} }
pub fn a_filesystem() -> TempFileSystem { pub fn a_filesystem() -> TempFileSystem {
kxio::fs::temp().expect("temp fs") kxio::fs::temp().expect("temp fs")
} }

View file

@ -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"
}
]

View file

@ -0,0 +1,69 @@
[
{
"id": "5abbe4b7ddc1b351ef961414",
"name": "Trello Platform Changes",
"desc": "Track changes to Trello's Platform on this board.",
"descData": "<string>",
"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": "<string>",
"selfJoin": true,
"cardCovers": true,
"isTemplate": true,
"cardAging": "pirate",
"calendarFeedEnabled": true,
"background": "5abbe4b7ddc1b351ef961414",
"backgroundImage": "<string>",
"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": "<string>",
"shortLink": "<string>",
"subscribed": true,
"powerUps": "<string>",
"dateLastActivity": "<string>",
"dateLastView": "<string>",
"idTags": "<string>",
"datePluginDisable": "<string>",
"creationMethod": "<string>",
"ixUpdate": 2154,
"templateGallery": "<string>",
"enterpriseOwned": true
}
]

View file

@ -1,17 +1,9 @@
// //
// use crate::trello::types::board::TrelloBoard;
// use color_eyre::Result; // use color_eyre::Result;
// use kxio::net::Net; // use kxio::net::Net;
//
// use crate::{ use crate::trello::types::{board::TrelloBoard, TrelloBoardName};
// f,
// trello::{
// types::{TrelloAuth, TrelloBoardId},
// url,
// },
// };
// use crate::trello::types::TrelloBoardName;
// pub async fn get_board( // pub async fn get_board(
// auth: &TrelloAuth, // auth: &TrelloAuth,
@ -31,11 +23,11 @@
// Ok(board) // Ok(board)
// } // }
// pub trait TrelloBoards { pub trait TrelloBoards {
// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard>; fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard>;
// } }
// impl TrelloBoards for Vec<TrelloBoard> { impl TrelloBoards for Vec<TrelloBoard> {
// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard> { fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard> {
// self.iter().find(|b| &b.name == board_name) self.iter().find(|b| &b.name == board_name)
// } }
// } }

View file

@ -27,13 +27,13 @@ impl<'cfg> TrelloAuth<'cfg> {
} }
pub const fn api_key(&self) -> &TrelloApiKey { pub const fn api_key(&self) -> &TrelloApiKey {
&self.api_key self.api_key
} }
pub const fn api_token(&self) -> &TrelloApiSecret { pub const fn api_token(&self) -> &TrelloApiSecret {
&self.api_secret self.api_secret
} }
} }
impl<'cfg> From<TrelloAuth<'cfg>> for HashMap<String, String> { impl From<TrelloAuth<'_>> for HashMap<String, String> {
fn from(value: TrelloAuth) -> Self { fn from(value: TrelloAuth) -> Self {
HashMap::from([( HashMap::from([(
"Authorization".into(), "Authorization".into(),