feat(nextcloud): add commnad 'nextcloud deck get'
Some checks failed
Test / build (map[name:stable]) (push) Failing after 5s
Release Please / Release-plz (push) Failing after 20s
Test / build (map[name:nightly]) (push) Failing after 8s

This commit is contained in:
Paul Campbell 2024-12-11 20:46:10 +00:00
parent d6c299e249
commit d90400d731
6 changed files with 222 additions and 56 deletions

View file

@ -74,7 +74,7 @@ As part of building the import server, the following commands exercise each oper
- [x] trello card get - includes list of attachments - [x] trello card get - includes list of attachments
- [x] trello attachment get - includes download url - [x] trello attachment get - includes download url
- [x] trello attachment save - saves to disk - [x] trello attachment save - saves to disk
- [ ] nextcloud deck get (was board list) - [x] nextcloud deck get - includes list of boards
- [ ] nextcloud board get (was stack list) - [ ] nextcloud board get (was stack list)
- [ ] nextcloud stack get (was card list) - [ ] nextcloud stack get (was card list)
- [x] nextcloud card create - [x] nextcloud card create

View file

@ -1,35 +0,0 @@
//
use clap::Parser;
use crate::execute::Execute;
use crate::{p, FullCtx};
#[derive(Parser, Debug)]
pub(crate) enum NextcloudBoardCommand {
List {
#[clap(long, action = clap::ArgAction::SetTrue)]
dump: bool,
},
}
impl Execute for NextcloudBoardCommand {
async fn execute(self, ctx: FullCtx) -> color_eyre::Result<()> {
match self {
Self::List { dump } => list(&ctx, dump).await,
}
}
}
pub(crate) async fn list(ctx: &FullCtx, dump: bool) -> color_eyre::Result<()> {
let api_result = ctx.deck_client().get_boards().await;
if dump {
p!(ctx.prt, "{}", api_result.text);
} else {
let mut boards = api_result.result?;
boards.sort_by_key(|stack| stack.title.clone());
boards
.iter()
.for_each(|stack| p!(ctx.prt, "{}:{}", stack.id, stack.title));
}
Ok(())
}

33
src/nextcloud/deck.rs Normal file
View file

@ -0,0 +1,33 @@
//
use clap::Parser;
use crate::execute::Execute;
use crate::{p, FullCtx};
#[derive(Parser, Debug)]
pub(crate) enum NextcloudDeckCommand {
Get {
#[clap(long, action = clap::ArgAction::SetTrue)]
dump: bool,
},
}
impl Execute for NextcloudDeckCommand {
async fn execute(self, ctx: FullCtx) -> color_eyre::Result<()> {
match self {
Self::Get { dump } => {
let api_result = ctx.deck_client().get_boards().await;
if dump {
p!(ctx.prt, "{}", api_result.text);
} else {
let mut boards = api_result.result?;
boards.sort_by_key(|stack| stack.title.clone());
boards
.iter()
.for_each(|stack| p!(ctx.prt, "{}:{}", stack.id, stack.title));
}
Ok(())
}
}
}
}

View file

@ -1,17 +1,19 @@
use crate::execute::Execute; //
use crate::nextcloud::board::NextcloudBoardCommand; use crate::{
use crate::nextcloud::card::NextcloudCardCommand; execute::Execute,
use crate::nextcloud::model::{ nextcloud::{
NextcloudBoardId, NextcloudHostname, NextcloudPassword, NextcloudUsername, card::NextcloudCardCommand,
deck::NextcloudDeckCommand,
model::{NextcloudBoardId, NextcloudHostname, NextcloudPassword, NextcloudUsername},
stack::NextcloudStackCommand,
},
FullCtx,
}; };
use crate::nextcloud::stack::NextcloudStackCommand;
use crate::FullCtx;
use clap::Parser; use clap::Parser;
//
mod board;
pub(crate) mod card; pub(crate) mod card;
pub(crate) mod client; pub(crate) mod client;
pub(crate) mod deck;
pub(crate) mod model; pub(crate) mod model;
mod stack; mod stack;
@ -21,7 +23,7 @@ mod tests;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub(crate) enum NextcloudCommand { pub(crate) enum NextcloudCommand {
#[clap(subcommand)] #[clap(subcommand)]
Board(NextcloudBoardCommand), Deck(NextcloudDeckCommand),
#[clap(subcommand)] #[clap(subcommand)]
Stack(NextcloudStackCommand), Stack(NextcloudStackCommand),
#[clap(subcommand)] #[clap(subcommand)]
@ -30,7 +32,7 @@ pub(crate) enum NextcloudCommand {
impl Execute for NextcloudCommand { impl Execute for NextcloudCommand {
async fn execute(self, ctx: FullCtx) -> color_eyre::Result<()> { async fn execute(self, ctx: FullCtx) -> color_eyre::Result<()> {
match self { match self {
NextcloudCommand::Board(cmd) => cmd.execute(ctx).await, NextcloudCommand::Deck(cmd) => cmd.execute(ctx).await,
NextcloudCommand::Stack(cmd) => cmd.execute(ctx).await, NextcloudCommand::Stack(cmd) => cmd.execute(ctx).await,
NextcloudCommand::Card(cmd) => cmd.execute(ctx).await, NextcloudCommand::Card(cmd) => cmd.execute(ctx).await,
} }

View file

@ -5,7 +5,6 @@ use serde_json::json;
use crate::{ use crate::{
execute::Execute, execute::Execute,
nextcloud::{ nextcloud::{
board::NextcloudBoardCommand,
card::{AddLabel, Create}, card::{AddLabel, Create},
model::{ model::{
Card, Label, NextcloudBoardId, NextcloudCardId, NextcloudCardTitle, NextcloudETag, Card, Label, NextcloudBoardId, NextcloudCardId, NextcloudCardTitle, NextcloudETag,
@ -110,11 +109,15 @@ mod config {
mod commands { mod commands {
use super::*; use super::*;
mod board { mod deck {
use super::*; use super::*;
use crate::execute::Execute;
use crate::nextcloud::deck::NextcloudDeckCommand;
use crate::nextcloud::NextcloudCommand;
use crate::Command;
#[tokio::test] #[tokio::test]
async fn list_dump() { async fn get_dump() {
//given //given
let mock_net = kxio::net::mock(); let mock_net = kxio::net::mock();
@ -123,7 +126,7 @@ mod commands {
.get("https://host-name/index.php/apps/deck/api/v1.0/boards") .get("https://host-name/index.php/apps/deck/api/v1.0/boards")
.basic_auth("username", Some("password")) .basic_auth("username", Some("password"))
.respond(StatusCode::OK) .respond(StatusCode::OK)
.body(include_str!("../tests/responses/nextcloud-board-list.json")) .body(include_str!("../tests/responses/nextcloud-deck-get.json"))
.expect("mock request"); .expect("mock request");
let fs = given::a_filesystem(); let fs = given::a_filesystem();
@ -132,22 +135,23 @@ mod commands {
let prt = prt.as_test().unwrap(); let prt = prt.as_test().unwrap();
//when //when
Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List { Command::Nextcloud(NextcloudCommand::Deck(NextcloudDeckCommand::Get {
dump: true, dump: true,
})) }))
.execute(ctx) .execute(ctx)
.await .await
.expect("execute"); .expect("execute");
//then
let output = prt.output(); let output = prt.output();
assert_eq!( assert_eq!(
output.trim(), output.trim(),
include_str!("../tests/responses/nextcloud-board-list.json").trim() include_str!("../tests/responses/nextcloud-deck-get.json").trim()
); );
} }
#[tokio::test] #[tokio::test]
async fn list_no_dump() { async fn get_no_dump() {
//given //given
let mock_net = kxio::net::mock(); let mock_net = kxio::net::mock();
@ -156,7 +160,7 @@ mod commands {
.get("https://host-name/index.php/apps/deck/api/v1.0/boards") .get("https://host-name/index.php/apps/deck/api/v1.0/boards")
.basic_auth("username", Some("password")) .basic_auth("username", Some("password"))
.respond(StatusCode::OK) .respond(StatusCode::OK)
.body(include_str!("../tests/responses/nextcloud-board-list.json")) .body(include_str!("../tests/responses/nextcloud-deck-get.json"))
.expect("mock request"); .expect("mock request");
let fs = given::a_filesystem(); let fs = given::a_filesystem();
@ -165,13 +169,14 @@ mod commands {
let prt = prt.as_test().unwrap(); let prt = prt.as_test().unwrap();
//when //when
Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List { Command::Nextcloud(NextcloudCommand::Deck(NextcloudDeckCommand::Get {
dump: false, dump: false,
})) }))
.execute(ctx) .execute(ctx)
.await .await
.expect("execute"); .expect("execute");
//then
let output = prt.output(); let output = prt.output();
assert_eq!( assert_eq!(
output.trim(), output.trim(),
@ -185,6 +190,81 @@ mod commands {
} }
} }
// mod board {
// use super::*;
//
// #[tokio::test]
// async fn list_dump() {
// //given
// let mock_net = kxio::net::mock();
//
// mock_net
// .on()
// .get("https://host-name/index.php/apps/deck/api/v1.0/boards")
// .basic_auth("username", Some("password"))
// .respond(StatusCode::OK)
// .body(include_str!("../tests/responses/nextcloud-board-list.json"))
// .expect("mock request");
//
// let fs = given::a_filesystem();
// let ctx = given::a_full_context(mock_net, fs);
// let prt = ctx.prt.clone();
// let prt = prt.as_test().unwrap();
//
// //when
// Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List {
// dump: true,
// }))
// .execute(ctx)
// .await
// .expect("execute");
//
// let output = prt.output();
// assert_eq!(
// output.trim(),
// include_str!("../tests/responses/nextcloud-board-list.json").trim()
// );
// }
//
// #[tokio::test]
// async fn list_no_dump() {
// //given
// let mock_net = kxio::net::mock();
//
// mock_net
// .on()
// .get("https://host-name/index.php/apps/deck/api/v1.0/boards")
// .basic_auth("username", Some("password"))
// .respond(StatusCode::OK)
// .body(include_str!("../tests/responses/nextcloud-board-list.json"))
// .expect("mock request");
//
// let fs = given::a_filesystem();
// let ctx = given::a_full_context(mock_net, fs);
// let prt = ctx.prt.clone();
// let prt = prt.as_test().unwrap();
//
// //when
// Command::Nextcloud(NextcloudCommand::Board(NextcloudBoardCommand::List {
// dump: false,
// }))
// .execute(ctx)
// .await
// .expect("execute");
//
// let output = prt.output();
// assert_eq!(
// output.trim(),
// [
// "4:4 Published: Cossmass Infinities",
// "5:Fulfilment: Cossmass Infinities",
// "1:Personal Board"
// ]
// .join("\n")
// );
// }
// }
mod stack { mod stack {
use super::*; use super::*;

View file

@ -0,0 +1,86 @@
[
{
"id": 1,
"title": "Personal Board",
"owner": {
"primaryKey": "pcampbell",
"uid": "pcampbell",
"displayname": "Paul Campbell",
"type": 0
},
"color": "0087C5",
"archived": false,
"labels": [],
"acl": [],
"permissions": {
"PERMISSION_READ": true,
"PERMISSION_EDIT": true,
"PERMISSION_MANAGE": true,
"PERMISSION_SHARE": true
},
"users": [],
"shared": 0,
"stacks": [],
"activeSessions": [],
"deletedAt": 0,
"lastModified": 1733695323,
"settings": [],
"ETag": "9de45fc7d68507f1eaef462e90e6414c"
},
{
"id": 4,
"title": "4 Published: Cossmass Infinities",
"owner": {
"primaryKey": "pcampbell",
"uid": "pcampbell",
"displayname": "Paul Campbell",
"type": 0
},
"color": "ff0000",
"archived": true,
"labels": [],
"acl": [],
"permissions": {
"PERMISSION_READ": true,
"PERMISSION_EDIT": true,
"PERMISSION_MANAGE": true,
"PERMISSION_SHARE": true
},
"users": [],
"shared": 0,
"stacks": [],
"activeSessions": [],
"deletedAt": 0,
"lastModified": 1699798570,
"settings": [],
"ETag": "5e0fe035f3b95672da3cba633086be37"
},
{
"id": 5,
"title": "Fulfilment: Cossmass Infinities",
"owner": {
"primaryKey": "pcampbell",
"uid": "pcampbell",
"displayname": "Paul Campbell",
"type": 0
},
"color": "ff0000",
"archived": true,
"labels": [],
"acl": [],
"permissions": {
"PERMISSION_READ": true,
"PERMISSION_EDIT": true,
"PERMISSION_MANAGE": true,
"PERMISSION_SHARE": true
},
"users": [],
"shared": 0,
"stacks": [],
"activeSessions": [],
"deletedAt": 0,
"lastModified": 1699798567,
"settings": [],
"ETag": "90e2f9d53c5f6ec83088425d4486e54d"
}
]