jira_cli/commands/issues/
create_meta.rs1use crate::api::{ApiError, JiraClient};
2use crate::output::OutputConfig;
3use serde_json::Value;
4
5pub async fn create_meta(
6 client: &JiraClient,
7 out: &OutputConfig,
8 project: &str,
9 issue_type: Option<&str>,
10) -> Result<(), ApiError> {
11 let metadata = client.issue_create_metadata(project, issue_type).await?;
12 if out.json {
13 out.print_result(&metadata, "");
14 return Ok(());
15 }
16 if issue_type.is_none() {
17 for item in metadata["issueTypes"].as_array().expect("issue type array") {
18 println!(
19 "{:<12} {}{}",
20 item["id"].as_str().unwrap_or(""),
21 item["name"].as_str().unwrap_or(""),
22 if item["subtask"] == true {
23 " (subtask)"
24 } else {
25 ""
26 }
27 );
28 }
29 out.print_message(&format!(
30 "Inspect a create screen with: jira issues create-meta -p {project} -t <TYPE>"
31 ));
32 return Ok(());
33 }
34 println!("{project}: {}", option_text(&metadata["issueType"]));
35 println!(
36 "Epic support: {}{}",
37 metadata["epic"]["status"].as_str().unwrap_or("unavailable"),
38 metadata["epic"]["field"]
39 .as_str()
40 .map(|id| format!(" ({id})"))
41 .unwrap_or_default()
42 );
43 if let Some(fields) = metadata["fields"].as_object() {
44 for (id, field) in fields {
45 let requirement = match field["required"].as_bool() {
46 Some(true) if field["hasDefaultValue"] == true => "required, default provided",
47 Some(true) => "required",
48 Some(false) => "optional",
49 None => "requirement unknown",
50 };
51 println!(
52 "\n{} [{id}]: {requirement}",
53 field["name"].as_str().unwrap_or(id)
54 );
55 if !field["defaultValue"].is_null() {
56 println!(" Default: {}", option_text(&field["defaultValue"]));
57 }
58 if let Some(options) = field["allowedValues"].as_array() {
59 let labels = options
60 .iter()
61 .map(option_text)
62 .collect::<Vec<_>>()
63 .join(", ");
64 println!(
65 " Allowed: {}",
66 if labels.is_empty() { "(none)" } else { &labels }
67 );
68 }
69 }
70 } else {
71 println!("Field metadata unavailable.");
72 }
73 for warning in metadata["warnings"].as_array().expect("warning array") {
74 out.print_message(warning.as_str().unwrap_or(""));
75 }
76 Ok(())
77}
78
79fn option_text(value: &Value) -> String {
80 if let Some(name) = value["name"].as_str().or_else(|| value["value"].as_str()) {
81 match value["id"].as_str() {
82 Some(id) => format!("{name} ({id})"),
83 None => name.into(),
84 }
85 } else if let Some(value) = value.as_str() {
86 value.into()
87 } else {
88 value.to_string()
89 }
90}