1mod attachments;
10mod comments;
11mod crud;
12mod transitions;
13
14use std::path::PathBuf;
15
16use anyhow::Result;
17use clap::Subcommand;
18
19use crate::output::OutputFormat;
20use raps_acc::IssuesClient;
21
22#[derive(Debug, Subcommand)]
23pub enum IssueCommands {
24 List {
26 project_id: String,
28
29 #[arg(short, long)]
31 status: Option<String>,
32
33 #[arg(long)]
35 since: Option<String>,
36 },
37
38 Create {
40 project_id: String,
42
43 #[arg(short, long)]
45 title: Option<String>,
46
47 #[arg(short, long)]
49 description: Option<String>,
50
51 #[arg(long, value_name = "FILE")]
53 from_csv: Option<PathBuf>,
54 },
55
56 Update {
58 project_id: String,
60 issue_id: String,
62
63 #[arg(short, long)]
65 status: Option<String>,
66
67 #[arg(short, long)]
69 title: Option<String>,
70 },
71
72 Types {
74 project_id: String,
76 },
77
78 #[command(subcommand)]
80 Comment(CommentCommands),
81
82 Attachments {
84 project_id: String,
86 issue_id: String,
88 },
89
90 Transition {
92 project_id: String,
94 issue_id: String,
96 #[arg(short, long)]
98 to: Option<String>,
99 },
100
101 Delete {
103 project_id: String,
105 issue_id: String,
107 },
108}
109
110#[derive(Debug, Subcommand)]
111pub enum CommentCommands {
112 List {
114 project_id: String,
116 issue_id: String,
118 },
119
120 Add {
122 project_id: String,
124 issue_id: String,
126 #[arg(short, long)]
128 body: String,
129 },
130
131 Delete {
133 project_id: String,
135 issue_id: String,
137 comment_id: String,
139 },
140}
141
142impl IssueCommands {
143 pub async fn execute(self, client: &IssuesClient, output_format: OutputFormat) -> Result<()> {
144 match self {
145 IssueCommands::List {
146 project_id,
147 status,
148 since,
149 } => crud::list_issues(client, &project_id, status, since, output_format).await,
150 IssueCommands::Create {
151 project_id,
152 title,
153 description,
154 from_csv,
155 } => {
156 crud::create_issue(
157 client,
158 &project_id,
159 title,
160 description,
161 from_csv,
162 output_format,
163 )
164 .await
165 }
166 IssueCommands::Update {
167 project_id,
168 issue_id,
169 status,
170 title,
171 } => {
172 crud::update_issue(client, &project_id, &issue_id, status, title, output_format)
173 .await
174 }
175 IssueCommands::Types { project_id } => {
176 crud::list_issue_types(client, &project_id, output_format).await
177 }
178 IssueCommands::Comment(cmd) => cmd.execute(client, output_format).await,
179 IssueCommands::Attachments {
180 project_id,
181 issue_id,
182 } => attachments::list_attachments(client, &project_id, &issue_id, output_format).await,
183 IssueCommands::Transition {
184 project_id,
185 issue_id,
186 to,
187 } => {
188 transitions::transition_issue(client, &project_id, &issue_id, to, output_format)
189 .await
190 }
191 IssueCommands::Delete {
192 project_id,
193 issue_id,
194 } => crud::delete_issue(client, &project_id, &issue_id, output_format).await,
195 }
196 }
197}
198
199impl CommentCommands {
200 pub async fn execute(self, client: &IssuesClient, output_format: OutputFormat) -> Result<()> {
201 match self {
202 CommentCommands::List {
203 project_id,
204 issue_id,
205 } => comments::list_comments(client, &project_id, &issue_id, output_format).await,
206 CommentCommands::Add {
207 project_id,
208 issue_id,
209 body,
210 } => comments::add_comment(client, &project_id, &issue_id, &body, output_format).await,
211 CommentCommands::Delete {
212 project_id,
213 issue_id,
214 comment_id,
215 } => {
216 comments::delete_comment(client, &project_id, &issue_id, &comment_id, output_format)
217 .await
218 }
219 }
220 }
221}
222
223pub(super) fn truncate_str(s: &str, max_len: usize) -> String {
225 if s.len() <= max_len {
226 s.to_string()
227 } else {
228 format!("{}...", &s[..max_len - 3])
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn test_truncate_str_short() {
238 assert_eq!(truncate_str("hello", 10), "hello");
239 }
240
241 #[test]
242 fn test_truncate_str_exact() {
243 assert_eq!(truncate_str("hello", 5), "hello");
244 }
245
246 #[test]
247 fn test_truncate_str_long() {
248 let result = truncate_str("hello world", 8);
249 assert_eq!(result, "hello...");
250 assert_eq!(result.len(), 8);
251 }
252}