feat: add APIResult
This is a generic type that contains the raw JSON response and the parsed value as a Result. fixup: APIResult FIXUP: APIResutl can handle missing response bodies
This commit is contained in:
parent
70aa002048
commit
766f0d4d49
32 changed files with 19734 additions and 2 deletions
|
@ -10,7 +10,7 @@ color-eyre = "0.6"
|
||||||
derive_more = { version = "1.0", features = [
|
derive_more = { version = "1.0", features = [
|
||||||
"as_ref",
|
"as_ref",
|
||||||
"constructor",
|
"constructor",
|
||||||
# "deref",
|
"deref",
|
||||||
# "display",
|
# "display",
|
||||||
# "from",
|
# "from",
|
||||||
#] }
|
#] }
|
||||||
|
@ -20,7 +20,7 @@ derive_more = { version = "1.0", features = [
|
||||||
# kxio = {path = "../kxio/"}
|
# kxio = {path = "../kxio/"}
|
||||||
kxio = "3.2"
|
kxio = "3.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
#serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tokio = { version = "1.41", features = ["full"] }
|
tokio = { version = "1.41", features = ["full"] }
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
#tracing= "0.1"
|
#tracing= "0.1"
|
||||||
|
|
32
src/api_result.rs
Normal file
32
src/api_result.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// use kxio::net::Response;
|
||||||
|
//
|
||||||
|
// use crate::{e, s};
|
||||||
|
|
||||||
|
// pub struct APIResult<T> {
|
||||||
|
// pub text: String,
|
||||||
|
// pub result: Result<T, kxio::net::Error>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T: for<'a> serde::Deserialize<'a>> APIResult<T> {
|
||||||
|
// pub async fn new(response: kxio::net::Result<Response>) -> Self {
|
||||||
|
// match response {
|
||||||
|
// Ok(response) => {
|
||||||
|
// let text = response.text().await.unwrap_or_default();
|
||||||
|
// let text = if text.is_empty() { s!("null") } else { text };
|
||||||
|
// let result = serde_json::from_str::<T>(&text)
|
||||||
|
// .map_err(|e| e.to_string())
|
||||||
|
// .map_err(|e| {
|
||||||
|
// e!("{e}: {text}");
|
||||||
|
// e
|
||||||
|
// })
|
||||||
|
// .map_err(kxio::net::Error::from);
|
||||||
|
// Self { text, result }
|
||||||
|
// }
|
||||||
|
// Err(e) => Self {
|
||||||
|
// text: s!(""),
|
||||||
|
// result: Err(e),
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -4,10 +4,12 @@ use std::path::PathBuf;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use kxio::{fs::FileSystem, net::Net};
|
use kxio::{fs::FileSystem, net::Net};
|
||||||
|
|
||||||
|
mod api_result;
|
||||||
mod config;
|
mod config;
|
||||||
mod init;
|
mod init;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod template;
|
mod template;
|
||||||
|
mod trello;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
41
src/trello/api/boards.rs
Normal file
41
src/trello/api/boards.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// pub async fn get_board(
|
||||||
|
// auth: &TrelloAuth,
|
||||||
|
// board_id: &TrelloBoardId,
|
||||||
|
// net: &Net,
|
||||||
|
// ) -> Result<TrelloBoard> {
|
||||||
|
// let board = net
|
||||||
|
// .get(url(f!(
|
||||||
|
// "/boards/{}/?fields=name&lists=all&list_fields=all&cards=all&card_fields=all",
|
||||||
|
// **board_id
|
||||||
|
// )))
|
||||||
|
// .headers(auth.into())
|
||||||
|
// .send()
|
||||||
|
// .await?
|
||||||
|
// .json()
|
||||||
|
// .await?;
|
||||||
|
// Ok(board)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub trait TrelloBoards {
|
||||||
|
// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard>;
|
||||||
|
// }
|
||||||
|
// impl TrelloBoards for Vec<TrelloBoard> {
|
||||||
|
// fn find_by_name(&self, board_name: &TrelloBoardName) -> Option<&TrelloBoard> {
|
||||||
|
// self.iter().find(|b| &b.name == board_name)
|
||||||
|
// }
|
||||||
|
// }
|
61
src/trello/api/cards/create.rs
Normal file
61
src/trello/api/cards/create.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
use color_eyre::Result;
|
||||||
|
use kxio::net::Net;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::trello::{
|
||||||
|
types::{NewTrelloCard, TrelloAuth, TrelloCard},
|
||||||
|
url,
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// POST /cards
|
||||||
|
///
|
||||||
|
/// Query Pparameters
|
||||||
|
///
|
||||||
|
/// - name string
|
||||||
|
/// The name for the card
|
||||||
|
/// - desc string
|
||||||
|
/// The description of the card
|
||||||
|
/// - pos string
|
||||||
|
/// The position of the card. top, bottom, or a positive number.
|
||||||
|
/// - due string
|
||||||
|
/// A due date for the card. A date
|
||||||
|
/// - start string
|
||||||
|
/// A start date for the card. A date, or null
|
||||||
|
/// - dueComplete bool
|
||||||
|
/// If the due date has been marked complete
|
||||||
|
/// - idList string REQUIRED
|
||||||
|
/// The ID of the list the card should be added to
|
||||||
|
/// - idMembers string
|
||||||
|
/// A comma-separated list of memberIds to add to the card
|
||||||
|
/// - idLabels string
|
||||||
|
/// A comma-separated list of labelIds to add to the card
|
||||||
|
pub async fn create_card(
|
||||||
|
auth: &TrelloAuth,
|
||||||
|
new_card: NewTrelloCard,
|
||||||
|
net: &Net,
|
||||||
|
) -> Result<TrelloCard> {
|
||||||
|
let card = net
|
||||||
|
.post(url("/cards"))
|
||||||
|
.headers(auth.into())
|
||||||
|
.body(
|
||||||
|
json!({
|
||||||
|
"idList": new_card.list_id(),
|
||||||
|
"name": new_card.name(),
|
||||||
|
"pos": "bottom",
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
Ok(card)
|
||||||
|
}
|
||||||
|
// #[derive(Debug, serde::Serialize)]
|
||||||
|
// pub struct CreateCardRequest {
|
||||||
|
// name: String,
|
||||||
|
// pos: String,
|
||||||
|
// }
|
21
src/trello/api/cards/delete.rs
Normal file
21
src/trello/api/cards/delete.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
use color_eyre::Result;
|
||||||
|
use kxio::net::Net;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
f,
|
||||||
|
trello::{types::TrelloAuth, url, TrelloCardId},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn delete_card(
|
||||||
|
auth: &TrelloAuth,
|
||||||
|
remote_task_id: &TrelloCardId,
|
||||||
|
net: &Net,
|
||||||
|
) -> Result<()> {
|
||||||
|
net.delete(url(f!("/cards/{remote_task_id}")))
|
||||||
|
.headers(auth.into())
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
96
src/trello/api/cards/get.rs
Normal file
96
src/trello/api/cards/get.rs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
use color_eyre::Result;
|
||||||
|
use kxio::net::Net;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
f,
|
||||||
|
trello::{
|
||||||
|
types::{TrelloAuth, TrelloCard},
|
||||||
|
url, TrelloCardId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get a Card
|
||||||
|
///
|
||||||
|
/// https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-id-get
|
||||||
|
///
|
||||||
|
/// GET /cards/{id}
|
||||||
|
///
|
||||||
|
/// Get a card by its ID
|
||||||
|
///
|
||||||
|
/// Request
|
||||||
|
///
|
||||||
|
/// Path parameters
|
||||||
|
///
|
||||||
|
/// id TrelloID REQUIRED
|
||||||
|
///
|
||||||
|
/// Query parameters
|
||||||
|
///
|
||||||
|
/// - fields string
|
||||||
|
/// Which fields to return.
|
||||||
|
/// Default: `all`
|
||||||
|
/// `all` or a comma-separated list of fields.
|
||||||
|
/// Defaults: `badges, checkItemStates, closed, dateLastActivity, desc, descData,
|
||||||
|
/// due, start, email, idBoard, idChecklists, idLabels, idList, idMembers, idShort, idAttachmentCover,
|
||||||
|
/// manualCoverAttachment, labels, name, pos, shortUrl, url`
|
||||||
|
///
|
||||||
|
/// - actions string
|
||||||
|
/// See the [Actions Nested Resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/#actions-nested-resource)
|
||||||
|
///
|
||||||
|
/// - attachments oneOf [string, boolean]
|
||||||
|
/// true, false, or cover
|
||||||
|
/// Default: false
|
||||||
|
///
|
||||||
|
/// - attachment_fields string
|
||||||
|
/// `all` or a comma-separated list of attachment fields
|
||||||
|
/// Default: `all`
|
||||||
|
///
|
||||||
|
/// - members boolean
|
||||||
|
/// Whether to return member objects for members on the card
|
||||||
|
/// Default: false
|
||||||
|
///
|
||||||
|
/// - member_fields string
|
||||||
|
/// `all` or a comma-separated list of member fields. Defaults: `avatarHash, fullName, initials, username`
|
||||||
|
///
|
||||||
|
/// - checkItemStates boolean
|
||||||
|
/// Whether to return checkItemState objects for checklists on the card
|
||||||
|
/// Default: false
|
||||||
|
///
|
||||||
|
/// - checklists string
|
||||||
|
/// Whether to return the checklists on the card. all or none
|
||||||
|
/// Default: none
|
||||||
|
///
|
||||||
|
/// - checklist_fields string
|
||||||
|
/// `all` or a comma-separated list of idBoard,idCard,name,pos
|
||||||
|
/// Default: `all`
|
||||||
|
///
|
||||||
|
/// - board boolean
|
||||||
|
/// Whether to return the board object the card is on
|
||||||
|
/// Default: false
|
||||||
|
///
|
||||||
|
/// - board_fields string
|
||||||
|
/// `all` or a comma-separated list of board fields. Defaults: `name, desc, descData, closed, idOrganization, pinned, url, prefs`
|
||||||
|
///
|
||||||
|
/// - list boolean
|
||||||
|
/// See the [Lists Nested Resource](https://developer.atlassian.com/cloud/trello/guides/rest-api/nested-resources/#lists-nested-resource)
|
||||||
|
///
|
||||||
|
/// Responses
|
||||||
|
///
|
||||||
|
/// 200 OK Success
|
||||||
|
///
|
||||||
|
/// application/json
|
||||||
|
pub async fn get_card(
|
||||||
|
auth: &TrelloAuth,
|
||||||
|
trello_card_id: &TrelloCardId,
|
||||||
|
net: &Net,
|
||||||
|
) -> Result<TrelloCard> {
|
||||||
|
let card = net
|
||||||
|
.get(url(f!("/cards/{trello_card_id}")))
|
||||||
|
.headers(auth.into())
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
Ok(card)
|
||||||
|
}
|
9
src/trello/api/cards/mod.rs
Normal file
9
src/trello/api/cards/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
mod create;
|
||||||
|
mod delete;
|
||||||
|
mod get;
|
||||||
|
mod update;
|
||||||
|
|
||||||
|
pub use create::create_card;
|
||||||
|
pub use delete::delete_card;
|
||||||
|
pub use get::get_card;
|
||||||
|
pub use update::{update_card, TrelloCardUpdate};
|
49
src/trello/api/cards/update.rs
Normal file
49
src/trello/api/cards/update.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
use color_eyre::Result;
|
||||||
|
use kxio::net::Net;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
f,
|
||||||
|
trello::{
|
||||||
|
types::{TrelloAuth, TrelloCard},
|
||||||
|
url, TrelloCardId, TrelloCardName, TrelloListId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn update_card(
|
||||||
|
auth: &TrelloAuth,
|
||||||
|
card_update: TrelloCardUpdate,
|
||||||
|
net: &Net,
|
||||||
|
) -> Result<TrelloCard> {
|
||||||
|
let net_url = url(f!("/cards/{}", card_update.id));
|
||||||
|
let card = net
|
||||||
|
.put(net_url)
|
||||||
|
.headers(auth.into())
|
||||||
|
.body(
|
||||||
|
json!({
|
||||||
|
"idList": card_update.id_list,
|
||||||
|
"name": card_update.name,
|
||||||
|
})
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
Ok(card)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, serde::Serialize)]
|
||||||
|
pub struct TrelloCardUpdate {
|
||||||
|
id: TrelloCardId,
|
||||||
|
name: TrelloCardName,
|
||||||
|
#[serde(rename = "idList")]
|
||||||
|
id_list: TrelloListId,
|
||||||
|
}
|
||||||
|
impl TrelloCardUpdate {
|
||||||
|
pub const fn new(id: TrelloCardId, name: TrelloCardName, id_list: TrelloListId) -> Self {
|
||||||
|
Self { id, name, id_list }
|
||||||
|
}
|
||||||
|
}
|
47
src/trello/api/lists.rs
Normal file
47
src/trello/api/lists.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
use color_eyre::Result;
|
||||||
|
use kxio::net::Net;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
f,
|
||||||
|
trello::{
|
||||||
|
types::{TrelloAuth, TrelloCard, TrelloList},
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get Cards in a List
|
||||||
|
///
|
||||||
|
/// https://developer.atlassian.com/cloud/trello/rest/api-group-lists/#api-lists-id-cards-get
|
||||||
|
///
|
||||||
|
/// GET /lists/{id}/cards
|
||||||
|
///
|
||||||
|
/// List the cards in a list
|
||||||
|
///
|
||||||
|
/// Request
|
||||||
|
///
|
||||||
|
/// Path parameters
|
||||||
|
///
|
||||||
|
/// id TrelloID REQUIRED
|
||||||
|
///
|
||||||
|
/// Responses
|
||||||
|
///
|
||||||
|
/// 200 OK Success
|
||||||
|
///
|
||||||
|
/// application/json
|
||||||
|
pub async fn get_lists_cards(
|
||||||
|
auth: &TrelloAuth,
|
||||||
|
list: &TrelloList,
|
||||||
|
net: &Net,
|
||||||
|
) -> Result<Vec<TrelloCard>> {
|
||||||
|
let net_url = url(f!("/lists/{}/cards", **list.id()));
|
||||||
|
let cards = net
|
||||||
|
.get(net_url)
|
||||||
|
.headers(auth.into())
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
Ok(cards)
|
||||||
|
}
|
54
src/trello/api/members.rs
Normal file
54
src/trello/api/members.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// use kxio::net::Net;
|
||||||
|
|
||||||
|
// use crate::api_result::APIResult;
|
||||||
|
// use crate::{
|
||||||
|
// f,
|
||||||
|
// trello::{
|
||||||
|
// types::{TrelloAuth, board::TrelloBoard},
|
||||||
|
// url,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// /// Get lists from named board that Member belongs to
|
||||||
|
// ///
|
||||||
|
// /// Get Boards that Member belongs to
|
||||||
|
// /// https://developer.atlassian.com/cloud/trello/rest/api-group-members/#api-members-id-boards-get
|
||||||
|
// /// /members/{id}/boards
|
||||||
|
// ///
|
||||||
|
// /// Lists the boards that the user is a member of.
|
||||||
|
// ///
|
||||||
|
// /// Request
|
||||||
|
// ///
|
||||||
|
// /// Path parameters
|
||||||
|
// ///
|
||||||
|
// /// - id TrelloID REQUIRED
|
||||||
|
// ///
|
||||||
|
// ///
|
||||||
|
// /// Query parameters
|
||||||
|
// ///
|
||||||
|
// /// - fields string
|
||||||
|
// /// Default: all
|
||||||
|
// /// Valid values: id, name, desc, descData, closed, idMemberCreator, idOrganization, pinned, url, shortUrl, prefs, labelNames, starred, limits, memberships, enterpriseOwned
|
||||||
|
// ///
|
||||||
|
// /// - lists string
|
||||||
|
// /// Which lists to include with the boards. One of: all, closed, none, open
|
||||||
|
// /// Default: none
|
||||||
|
// /// Valid values: all, closed, none, open
|
||||||
|
// ///
|
||||||
|
// /// curl --request GET \
|
||||||
|
// /// --url "https://api.trello.com/1/members/$TRELLO_USERNAME/boards?key=$TRELLO_KEY&token=$TRELLO_SECRET&lists=open" \
|
||||||
|
// /// --header 'Accept: application/json'
|
||||||
|
// pub async fn get_boards_that_member_belongs_to(
|
||||||
|
// auth: &TrelloAuth,
|
||||||
|
// net: &Net,
|
||||||
|
// ) -> APIResult<Vec<TrelloBoard>> {
|
||||||
|
// APIResult::new(
|
||||||
|
// net.get(url(f!("/members/{}/boards?lists=open", **auth.user())))
|
||||||
|
// .headers(auth.into())
|
||||||
|
// .header("Accept", "application/json")
|
||||||
|
// .send()
|
||||||
|
// .await,
|
||||||
|
// )
|
||||||
|
// .await
|
||||||
|
// }
|
9
src/trello/api/mod.rs
Normal file
9
src/trello/api/mod.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
pub mod boards;
|
||||||
|
// pub mod cards;
|
||||||
|
// pub mod lists;
|
||||||
|
pub mod members;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
15
src/trello/api/tests/given.rs
Normal file
15
src/trello/api/tests/given.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// use kxio::net::MockNet;
|
||||||
|
|
||||||
|
// use crate::trello::types::auth::{TrelloApiKey, TrelloApiSecret, TrelloAuth, TrelloUser};
|
||||||
|
|
||||||
|
// pub(crate) fn a_network() -> MockNet {
|
||||||
|
// kxio::net::mock()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub(crate) fn an_auth() -> TrelloAuth {
|
||||||
|
// TrelloAuth::new(
|
||||||
|
// TrelloApiKey::new("foo"),
|
||||||
|
// TrelloApiSecret::new("bar"),
|
||||||
|
// TrelloUser::new("baz"),
|
||||||
|
// )
|
||||||
|
// }
|
59
src/trello/api/tests/mod.rs
Normal file
59
src/trello/api/tests/mod.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// use super::*;
|
||||||
|
|
||||||
|
mod given;
|
||||||
|
|
||||||
|
// type TestResult = color_eyre::Result<()>;
|
||||||
|
|
||||||
|
mod members {
|
||||||
|
|
||||||
|
// use std::collections::HashMap;
|
||||||
|
|
||||||
|
// use kxio::net::StatusCode;
|
||||||
|
// use serde_json::json;
|
||||||
|
|
||||||
|
// use crate::{
|
||||||
|
// s,
|
||||||
|
// trello::{
|
||||||
|
// // api::members::get_boards_that_member_belongs_to,
|
||||||
|
// types::{board::TrelloBoard, TrelloBoardId, TrelloBoardName},
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// use super::*;
|
||||||
|
//
|
||||||
|
// #[tokio::test]
|
||||||
|
// async fn get_member_boards() -> TestResult {
|
||||||
|
// //given
|
||||||
|
// let net = given::a_network();
|
||||||
|
// let auth = given::an_auth();
|
||||||
|
//
|
||||||
|
// net.on()
|
||||||
|
// .get("https://api.trello.com/1/members/baz/boards?lists=open")
|
||||||
|
// .headers(HashMap::from([
|
||||||
|
// (
|
||||||
|
// s!("authorization"),
|
||||||
|
// s!("OAuth oauth_consumer_key=\"foo\", oauth_token=\"bar\""),
|
||||||
|
// ),
|
||||||
|
// (s!("accept"), s!("application/json")),
|
||||||
|
// ]))
|
||||||
|
// .respond(StatusCode::OK)
|
||||||
|
// .body(s!(json!([
|
||||||
|
// {"id": "1", "name": "board-1", "lists":[]}
|
||||||
|
// ])))?;
|
||||||
|
//
|
||||||
|
// //when
|
||||||
|
// let result = get_boards_that_member_belongs_to(&auth, &net.into()).await;
|
||||||
|
//
|
||||||
|
// assert_eq!(
|
||||||
|
// result.result?,
|
||||||
|
// vec![TrelloBoard::new(
|
||||||
|
// TrelloBoardId::new("1"),
|
||||||
|
// TrelloBoardName::new("board-1"),
|
||||||
|
// vec![]
|
||||||
|
// )]
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// //then
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
}
|
14
src/trello/mod.rs
Normal file
14
src/trello/mod.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//
|
||||||
|
pub mod api;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
// use crate::f;
|
||||||
|
|
||||||
|
// pub fn url(path: impl Into<String>) -> String {
|
||||||
|
// let path = path.into();
|
||||||
|
// assert!(path.starts_with("/"));
|
||||||
|
// f!("https://api.trello.com/1{path}")
|
||||||
|
// }
|
1
src/trello/test_data/boards/empty.json
Normal file
1
src/trello/test_data/boards/empty.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[]
|
6048
src/trello/test_data/boards/no-lists.json
Normal file
6048
src/trello/test_data/boards/no-lists.json
Normal file
File diff suppressed because it is too large
Load diff
88
src/trello/test_data/get_card.json
Normal file
88
src/trello/test_data/get_card.json
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
{
|
||||||
|
"id": "list-1-card-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "id-for-inbox-5dbd5a88b09f840da3174607",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {
|
||||||
|
"status": "ok",
|
||||||
|
"disableAt": 36000,
|
||||||
|
"warnAt": 32400
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "👋 What? Why? How?",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
86
src/trello/test_data/get_lists_cards.json
Normal file
86
src/trello/test_data/get_lists_cards.json
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "👋 What? Why? How?",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
6149
src/trello/test_data/get_members_boards_lists.json
Normal file
6149
src/trello/test_data/get_members_boards_lists.json
Normal file
File diff suppressed because it is too large
Load diff
86
src/trello/test_data/list-1-cards.json
Normal file
86
src/trello/test_data/list-1-cards.json
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "👋 What? Why? How?",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
86
src/trello/test_data/list-2-cards.json
Normal file
86
src/trello/test_data/list-2-cards.json
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef061414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-2-5list-2-abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "Card from list 2",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
6149
src/trello/test_data/query_tasks/boards.json
Normal file
6149
src/trello/test_data/query_tasks/boards.json
Normal file
File diff suppressed because it is too large
Load diff
170
src/trello/test_data/query_tasks/list-1-cards.json
Normal file
170
src/trello/test_data/query_tasks/list-1-cards.json
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "list-1-card-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "List 1 Card 1",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"id": "list-1-card-2-5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "List 1 Card 2",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
170
src/trello/test_data/query_tasks/list-2-cards.json
Normal file
170
src/trello/test_data/query_tasks/list-2-cards.json
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "list-2-card-1-5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-2-5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "List 2 Card 1",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"id": "list-2-card-2-5abbe4b7ddc1b351ef961414",
|
||||||
|
"address": "<string>",
|
||||||
|
"badges": {
|
||||||
|
"attachmentsByType": {
|
||||||
|
"trello": {
|
||||||
|
"board": 2154,
|
||||||
|
"card": 2154
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"location": true,
|
||||||
|
"votes": 2154,
|
||||||
|
"viewingMemberVoted": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"fogbugz": "<string>",
|
||||||
|
"checkItems": 0,
|
||||||
|
"checkItemsChecked": 0,
|
||||||
|
"comments": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"description": true,
|
||||||
|
"due": "<string>",
|
||||||
|
"start": "<string>",
|
||||||
|
"dueComplete": true
|
||||||
|
},
|
||||||
|
"checkItemStates": [
|
||||||
|
"<string>"
|
||||||
|
],
|
||||||
|
"closed": true,
|
||||||
|
"coordinates": "<string>",
|
||||||
|
"creationMethod": "<string>",
|
||||||
|
"dateLastActivity": "2019-09-16T16:19:17.156Z",
|
||||||
|
"desc": "👋Hey there,\n\nTrello's Platform team uses this board to keep developers up-to-date.",
|
||||||
|
"descData": {
|
||||||
|
"emoji": {}
|
||||||
|
},
|
||||||
|
"due": "<string>",
|
||||||
|
"dueReminder": "<string>",
|
||||||
|
"email": "bentleycook+2kea95u7kchsvqnxkwe+2q0byi6qv4pt9uc7q5m+25qyyohtzg@boards.trello.com",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idChecklists": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idLabels": [
|
||||||
|
{
|
||||||
|
"id": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"idBoard": "5abbe4b7ddc1b351ef961414",
|
||||||
|
"name": "Overdue",
|
||||||
|
"color": "yellow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idList": "list-2-5abbe4b7ddc1b351ef961414",
|
||||||
|
"idMembers": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idMembersVoted": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"idShort": 2154,
|
||||||
|
"labels": [
|
||||||
|
"5abbe4b7ddc1b351ef961414"
|
||||||
|
],
|
||||||
|
"limits": {
|
||||||
|
"attachments": {
|
||||||
|
"perBoard": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locationName": "<string>",
|
||||||
|
"manualCoverAttachment": false,
|
||||||
|
"name": "List 2 Card 2",
|
||||||
|
"pos": 65535,
|
||||||
|
"shortLink": "H0TZyzbK",
|
||||||
|
"shortUrl": "https://trello.com/c/H0TZyzbK",
|
||||||
|
"subscribed": false,
|
||||||
|
"url": "https://trello.com/c/H0TZyzbK/4-%F0%9F%91%8B-what-why-how",
|
||||||
|
"cover": {
|
||||||
|
"color": "yellow",
|
||||||
|
"idUploadedBackground": true,
|
||||||
|
"size": "normal",
|
||||||
|
"brightness": "light",
|
||||||
|
"isTemplate": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
58
src/trello/tests.rs
Normal file
58
src/trello/tests.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::s;
|
||||||
|
use crate::trello::types::auth::TrelloAuth;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
mod board {
|
||||||
|
// use crate::trello::{
|
||||||
|
// // api::boards::TrelloBoards as _,
|
||||||
|
// types::{
|
||||||
|
// board::TrelloBoard, TrelloBoardId, TrelloBoardName, TrelloListId, TrelloListName,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn list_of_boards_find_by_name_returns_board() {
|
||||||
|
// //given
|
||||||
|
// let board = TrelloBoard::new(
|
||||||
|
// TrelloBoardId::new("2"),
|
||||||
|
// TrelloBoardName::new("beta"),
|
||||||
|
// vec![],
|
||||||
|
// );
|
||||||
|
// let boards = vec![
|
||||||
|
// TrelloBoard::new(
|
||||||
|
// TrelloBoardId::new("1"),
|
||||||
|
// TrelloBoardName::new("alpha"),
|
||||||
|
// vec![],
|
||||||
|
// ),
|
||||||
|
// board.clone(),
|
||||||
|
// TrelloBoard::new(
|
||||||
|
// TrelloBoardId::new("3"),
|
||||||
|
// TrelloBoardName::new("gamma"),
|
||||||
|
// vec![],
|
||||||
|
// ),
|
||||||
|
// ];
|
||||||
|
//
|
||||||
|
// //when
|
||||||
|
// let result = boards.find_by_name(board.name());
|
||||||
|
//
|
||||||
|
// //then
|
||||||
|
// assert_eq!(result, Some(&board));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trello_auth_into_hashmap() {
|
||||||
|
//given
|
||||||
|
let trello_auth = TrelloAuth {
|
||||||
|
api_key: s!("key").into(),
|
||||||
|
api_secret: s!("token").into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
//when
|
||||||
|
let result = HashMap::<String, String>::from(&trello_auth);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assert_eq!(result, HashMap::from([
|
||||||
|
(s!("Authorization"), s!("OAuth oauth_consumer_key=\"key\", oauth_token=\"token\"")),
|
||||||
|
]));
|
||||||
|
}
|
47
src/trello/types/auth.rs
Normal file
47
src/trello/types/auth.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
//
|
||||||
|
use derive_more::derive::Display;
|
||||||
|
|
||||||
|
use crate::newtype;
|
||||||
|
|
||||||
|
newtype!(TrelloApiKey, String, Display, "API Key");
|
||||||
|
newtype!(
|
||||||
|
TrelloApiSecret,
|
||||||
|
String,
|
||||||
|
Display,
|
||||||
|
"API Secret token for Trello"
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TrelloAuth {
|
||||||
|
pub(crate) api_key: TrelloApiKey,
|
||||||
|
pub(crate) api_secret: TrelloApiSecret,
|
||||||
|
}
|
||||||
|
impl TrelloAuth {
|
||||||
|
pub const fn new(api_key: TrelloApiKey, api_secret: TrelloApiSecret) -> Self {
|
||||||
|
Self {
|
||||||
|
api_key,
|
||||||
|
api_secret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn api_key(&self) -> &TrelloApiKey {
|
||||||
|
&self.api_key
|
||||||
|
}
|
||||||
|
pub const fn api_token(&self) -> &TrelloApiSecret {
|
||||||
|
&self.api_secret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&TrelloAuth> for HashMap<String, String> {
|
||||||
|
fn from(value: &TrelloAuth) -> Self {
|
||||||
|
HashMap::from([(
|
||||||
|
"Authorization".into(),
|
||||||
|
format!(
|
||||||
|
r#"OAuth oauth_consumer_key="{}", oauth_token="{}""#,
|
||||||
|
value.api_key(),
|
||||||
|
value.api_token()
|
||||||
|
),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
}
|
13
src/trello/types/board.rs
Normal file
13
src/trello/types/board.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
//
|
||||||
|
use derive_more::derive::Constructor;
|
||||||
|
|
||||||
|
use crate::trello::types::list::TrelloList;
|
||||||
|
|
||||||
|
use super::{TrelloBoardId, TrelloBoardName};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, Constructor)]
|
||||||
|
pub(crate) struct TrelloBoard {
|
||||||
|
pub(crate) id: TrelloBoardId,
|
||||||
|
pub(crate) name: TrelloBoardName,
|
||||||
|
pub(crate) lists: Vec<TrelloList>,
|
||||||
|
}
|
20
src/trello/types/card.rs
Normal file
20
src/trello/types/card.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
use crate::trello::{api::cards::TrelloCardUpdate, TrelloCardId, TrelloCardName, TrelloListId};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct TrelloCard {
|
||||||
|
id: TrelloCardId,
|
||||||
|
name: TrelloCardName,
|
||||||
|
#[serde(rename = "idList")]
|
||||||
|
id_list: TrelloListId,
|
||||||
|
}
|
||||||
|
impl TrelloCard {
|
||||||
|
#[cfg(test)]
|
||||||
|
pub const fn new(id: TrelloCardId, name: TrelloCardName, id_list: TrelloListId) -> Self {
|
||||||
|
Self { id, name, id_list }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn list_id(&self) -> &TrelloListId {
|
||||||
|
&self.id_list
|
||||||
|
}
|
||||||
|
}
|
9
src/trello/types/list.rs
Normal file
9
src/trello/types/list.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use derive_more::derive::Constructor;
|
||||||
|
|
||||||
|
use super::{TrelloListId, TrelloListName};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, Constructor)]
|
||||||
|
pub(crate) struct TrelloList {
|
||||||
|
pub(crate) id: TrelloListId,
|
||||||
|
pub(crate) name: TrelloListName,
|
||||||
|
}
|
23
src/trello/types/mod.rs
Normal file
23
src/trello/types/mod.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
pub(crate) mod auth;
|
||||||
|
pub(crate) mod board;
|
||||||
|
// mod card;
|
||||||
|
mod list;
|
||||||
|
// mod new_card;
|
||||||
|
|
||||||
|
use derive_more::derive::Display;
|
||||||
|
|
||||||
|
use crate::newtype;
|
||||||
|
|
||||||
|
newtype!(TrelloBoardId, String, Display, "Board ID");
|
||||||
|
newtype!(TrelloBoardName, String, Display, "Board Name");
|
||||||
|
newtype!(TrelloListId, String, "List ID");
|
||||||
|
newtype!(
|
||||||
|
TrelloListName,
|
||||||
|
String,
|
||||||
|
Display,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
"List Name"
|
||||||
|
);
|
||||||
|
newtype!(TrelloCardId, String, Display, "Card ID");
|
||||||
|
newtype!(TrelloCardName, String, Display, "Card Name");
|
20
src/trello/types/new_card.rs
Normal file
20
src/trello/types/new_card.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use super::{TrelloCardName, TrelloListId};
|
||||||
|
|
||||||
|
pub struct NewTrelloCard {
|
||||||
|
name: TrelloCardName,
|
||||||
|
list_id: TrelloListId,
|
||||||
|
}
|
||||||
|
impl NewTrelloCard {
|
||||||
|
pub fn new(name: impl Into<TrelloCardName>, list_id: impl Into<TrelloListId>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.into(),
|
||||||
|
list_id: list_id.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const fn name(&self) -> &TrelloCardName {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
pub const fn list_id(&self) -> &TrelloListId {
|
||||||
|
&self.list_id
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue