Skip to main content

jira_cli/commands/issues/
create_meta.rs

1use 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}