1use crate::card::Card;
2use crate::client::TrelloClient;
3use crate::formatting::header;
4use crate::trello_error::TrelloError;
5use crate::trello_object::{Renderable, TrelloObject};
6
7use colored::*;
8use regex::RegexBuilder;
9use serde::Deserialize;
10
11type Result<T> = std::result::Result<T, TrelloError>;
12
13#[derive(Deserialize, Debug, Eq, PartialEq, Clone)]
15#[serde(rename_all = "camelCase")]
16pub struct List {
17 pub id: String,
18 pub name: String,
19 pub closed: bool,
20 pub cards: Option<Vec<Card>>,
21}
22
23impl TrelloObject for List {
24 fn get_type() -> String {
25 String::from("List")
26 }
27
28 fn get_name(&self) -> &str {
29 &self.name
30 }
31
32 fn get_fields() -> &'static [&'static str] {
33 &["id", "name", "closed"]
34 }
35}
36
37impl Renderable for List {
38 fn render(&self, headers: bool) -> String {
39 let title = header(&self.name, "-").bold().to_string();
40 let mut result: Vec<String> = match headers {
41 true => vec![title],
42 false => vec![],
43 };
44 if let Some(cards) = &self.cards {
45 for c in cards {
46 result.push(format!("* {}", c.simple_render()));
47 }
48 }
49 result.join("\n")
50 }
51
52 fn simple_render(&self) -> String {
53 self.name.clone()
54 }
55}
56
57impl List {
58 pub fn new(id: &str, name: &str, cards: Option<Vec<Card>>) -> List {
59 List {
60 id: String::from(id),
61 name: String::from(name),
62 cards,
63 closed: false,
64 }
65 }
66
67 pub fn filter(&self, label_filter: &str) -> List {
103 let re = RegexBuilder::new(label_filter)
104 .case_insensitive(true)
105 .build()
106 .expect("Invalid regex for label filter");
107
108 let closure = |c: &Card| -> bool {
109 if let Some(labels) = &c.labels {
110 for label in labels {
111 if re.is_match(&label.name) {
112 return true;
113 }
114 }
115 }
116 false
117 };
118
119 let mut result = self.clone();
120 result.cards = result
121 .cards
122 .map(|cards| cards.into_iter().filter(closure).collect());
123 result
124 }
125
126 pub fn create(client: &TrelloClient, board_id: &str, name: &str) -> Result<List> {
127 let url = client.config.get_trello_url("/1/lists/", &[])?;
128
129 let params = [("name", name), ("idBoard", board_id)];
130
131 Ok(client
132 .client
133 .post(url)
134 .form(¶ms)
135 .send()?
136 .error_for_status()?
137 .json()?)
138 }
139
140 pub fn open(client: &TrelloClient, list_id: &str) -> Result<List> {
141 let url = client
142 .config
143 .get_trello_url(&format!("/1/lists/{}", &list_id), &[])?;
144
145 let params = [("closed", "false")];
146
147 Ok(client
148 .client
149 .put(url)
150 .form(¶ms)
151 .send()?
152 .error_for_status()?
153 .json()?)
154 }
155
156 pub fn update(client: &TrelloClient, list: &List) -> Result<List> {
157 let url = client
158 .config
159 .get_trello_url(&format!("/1/lists/{}/", &list.id), &[])?;
160
161 let params = [("name", &list.name), ("closed", &list.closed.to_string())];
162
163 Ok(client
164 .client
165 .put(url)
166 .form(¶ms)
167 .send()?
168 .error_for_status()?
169 .json()?)
170 }
171
172 pub fn get_all(client: &TrelloClient, board_id: &str, cards: bool) -> Result<Vec<List>> {
173 let fields = List::get_fields().join(",");
174 let mut params = vec![("fields", fields.as_str())];
175
176 if cards {
177 params.push(("cards", "open"));
178 }
179
180 let url = client
181 .config
182 .get_trello_url(&format!("/1/boards/{}/lists", board_id), ¶ms)?;
183
184 Ok(client.client.get(url).send()?.error_for_status()?.json()?)
185 }
186}