use clap::Subcommand;
use serde_json;
use crate::client::apis::configuration::Configuration;
use crate::client::apis::default_api;
use crate::client::commands::output::{print_if_json, print_json_wrapped};
use crate::client::commands::{get_env_user_name, pagination};
use crate::client::commands::{
print_error, select_workflow_interactively, table_format::display_table_with_count,
};
use crate::models;
use tabled::Tabled;
#[derive(Tabled)]
struct UserDataTableRow {
#[tabled(rename = "ID")]
id: i64,
#[tabled(rename = "Name")]
name: String,
#[tabled(rename = "Ephemeral")]
ephemeral: String,
#[tabled(rename = "Data Preview")]
data_preview: String,
}
#[derive(Subcommand)]
#[command(after_long_help = "\
EXAMPLES:
# List user data for a workflow
torc user-data list 123
# Get JSON output
torc -f json user-data list 123
# Find missing user data
torc user-data list-missing 123
")]
pub enum UserDataCommands {
#[command(after_long_help = "\
EXAMPLES:
torc user-data create 123 --name config --data '{\"key\": \"value\"}'
torc user-data create 123 --name temp_data --ephemeral
")]
Create {
#[arg()]
workflow_id: Option<i64>,
#[arg(short, long)]
name: String,
#[arg(short, long)]
data: Option<String>,
#[arg(long)]
ephemeral: bool,
#[arg(long)]
consumer_job_id: Option<i64>,
#[arg(long)]
producer_job_id: Option<i64>,
},
List {
workflow_id: Option<i64>,
#[arg(short, long, default_value = "50")]
limit: i64,
#[arg(short, long, default_value = "0")]
offset: i64,
#[arg(long)]
sort_by: Option<String>,
#[arg(long)]
reverse_sort: bool,
#[arg(long)]
name: Option<String>,
#[arg(long)]
is_ephemeral: Option<bool>,
#[arg(long)]
consumer_job_id: Option<i64>,
#[arg(long)]
producer_job_id: Option<i64>,
},
Get {
id: i64,
},
Update {
id: i64,
#[arg(short, long)]
name: Option<String>,
#[arg(short, long)]
data: Option<String>,
#[arg(long)]
ephemeral: Option<bool>,
},
Delete {
id: i64,
},
DeleteAll {
workflow_id: i64,
},
ListMissing {
workflow_id: i64,
},
}
pub fn handle_user_data_commands(config: &Configuration, command: &UserDataCommands, format: &str) {
match command {
UserDataCommands::Create {
workflow_id,
name,
data,
ephemeral,
consumer_job_id,
producer_job_id,
} => {
let user_name = crate::client::commands::get_env_user_name();
let wf_id = workflow_id.unwrap_or_else(|| {
select_workflow_interactively(config, &user_name).unwrap_or_else(|e| {
eprintln!("Error selecting workflow: {}", e);
std::process::exit(1);
})
});
let mut user_data = models::UserDataModel::new(wf_id, name.clone());
if let Some(data_str) = data {
match serde_json::from_str::<serde_json::Value>(data_str) {
Ok(json_data) => {
user_data.data = Some(json_data);
}
Err(e) => {
eprintln!("Error parsing JSON data: {}", e);
std::process::exit(1);
}
}
}
user_data.is_ephemeral = Some(*ephemeral);
match default_api::create_user_data(
config,
user_data,
*consumer_job_id,
*producer_job_id,
) {
Ok(created_user_data) => {
if print_if_json(format, &created_user_data, "user data") {
} else {
println!("Successfully created user data:");
println!(" ID: {}", created_user_data.id.unwrap_or(-1));
println!(" Workflow ID: {}", created_user_data.workflow_id);
println!(" Name: {:?}", created_user_data.name);
println!(" Is Ephemeral: {:?}", created_user_data.is_ephemeral);
if let Some(data) = &created_user_data.data {
println!(
" Data: {}",
serde_json::to_string_pretty(data).unwrap_or_default()
);
}
}
}
Err(e) => {
print_error("creating user data", &e);
std::process::exit(1);
}
}
}
UserDataCommands::List {
workflow_id,
limit,
offset,
sort_by,
reverse_sort,
name,
is_ephemeral,
consumer_job_id,
producer_job_id,
} => {
let user_name = get_env_user_name();
let selected_workflow_id = match workflow_id {
Some(id) => *id,
None => select_workflow_interactively(config, &user_name).unwrap(),
};
let mut params = pagination::UserDataListParams::new()
.with_offset(*offset)
.with_limit(*limit)
.with_reverse_sort(*reverse_sort);
if let Some(consumer_id) = consumer_job_id {
params = params.with_consumer_job_id(*consumer_id);
}
if let Some(producer_id) = producer_job_id {
params = params.with_producer_job_id(*producer_id);
}
if let Some(sort_field) = sort_by {
params = params.with_sort_by(sort_field.clone());
}
if let Some(name_filter) = name {
params = params.with_name(name_filter.clone());
}
if let Some(ephemeral_filter) = is_ephemeral {
params = params.with_is_ephemeral(*ephemeral_filter);
}
match pagination::paginate_user_data(config, selected_workflow_id, params) {
Ok(user_data_list) => {
if format == "json" {
print_json_wrapped("user_data", &user_data_list, "user_data");
} else if user_data_list.is_empty() {
println!(
"No user data found for workflow ID: {}",
selected_workflow_id
);
} else {
println!("User data for workflow ID {}:", selected_workflow_id);
let rows: Vec<UserDataTableRow> = user_data_list
.iter()
.map(|user_data| UserDataTableRow {
id: user_data.id.unwrap_or(-1),
name: user_data.name.clone(),
ephemeral: user_data
.is_ephemeral
.map_or("N/A".to_string(), |e| e.to_string()),
data_preview: user_data
.data
.as_ref()
.and_then(|d| serde_json::to_string(d).ok())
.unwrap_or_else(|| "N/A".to_string()),
})
.collect();
display_table_with_count(&rows, "user data records");
}
}
Err(e) => {
print_error("listing user data", &e);
std::process::exit(1);
}
}
}
UserDataCommands::Get { id } => match default_api::get_user_data(config, *id) {
Ok(user_data) => {
if print_if_json(format, &user_data, "user data") {
} else {
println!("User data ID {}:", id);
println!(" Workflow ID: {}", user_data.workflow_id);
println!(" Name: {}", user_data.name);
println!(" Is Ephemeral: {:?}", user_data.is_ephemeral);
if let Some(data) = &user_data.data {
println!(
" Data: {}",
serde_json::to_string_pretty(data).unwrap_or_default()
);
} else {
println!(" Data: None");
}
}
}
Err(e) => {
print_error("getting user data", &e);
std::process::exit(1);
}
},
UserDataCommands::Update {
id,
name,
data,
ephemeral,
} => {
match default_api::get_user_data(config, *id) {
Ok(mut user_data) => {
if let Some(new_name) = name {
user_data.name = new_name.clone();
}
if let Some(data_str) = data {
match serde_json::from_str::<serde_json::Value>(data_str) {
Ok(json_data) => {
user_data.data = Some(json_data);
}
Err(e) => {
eprintln!("Error parsing JSON data: {}", e);
std::process::exit(1);
}
}
}
if let Some(new_ephemeral) = ephemeral {
user_data.is_ephemeral = Some(*new_ephemeral);
}
match default_api::update_user_data(config, *id, user_data) {
Ok(updated_user_data) => {
if print_if_json(format, &updated_user_data, "user data") {
} else {
println!("Successfully updated user data:");
println!(" ID: {}", updated_user_data.id.unwrap_or(-1));
println!(" Workflow ID: {}", updated_user_data.workflow_id);
println!(" Name: {:?}", updated_user_data.name);
println!(" Is Ephemeral: {:?}", updated_user_data.is_ephemeral);
if let Some(data) = &updated_user_data.data {
println!(
" Data: {}",
serde_json::to_string_pretty(data).unwrap_or_default()
);
}
}
}
Err(e) => {
print_error("updating user data", &e);
std::process::exit(1);
}
}
}
Err(e) => {
print_error("getting user data for update", &e);
std::process::exit(1);
}
}
}
UserDataCommands::Delete { id } => match default_api::delete_user_data(config, *id, None) {
Ok(removed_user_data) => {
if print_if_json(format, &removed_user_data, "user data") {
} else {
println!("Successfully removed user data:");
println!(" ID: {}", removed_user_data.id.unwrap_or(-1));
println!(" Workflow ID: {}", removed_user_data.workflow_id);
println!(" Name: {:?}", removed_user_data.name);
}
}
Err(e) => {
print_error("removing user data", &e);
std::process::exit(1);
}
},
UserDataCommands::DeleteAll { workflow_id } => {
match default_api::delete_all_user_data(config, *workflow_id, None) {
Ok(_) => {
if format == "json" {
println!(
"{{\"message\": \"All user data deleted for workflow {}\"}}",
workflow_id
);
} else {
println!(
"Successfully deleted all user data for workflow ID: {}",
workflow_id
);
}
}
Err(e) => {
print_error("deleting user data", &e);
std::process::exit(1);
}
}
}
UserDataCommands::ListMissing { workflow_id } => {
match default_api::list_missing_user_data(config, *workflow_id) {
Ok(missing_data) => {
if print_if_json(format, &missing_data, "missing user data") {
} else if missing_data.user_data.is_empty() {
println!("No missing user data for workflow ID: {}", workflow_id);
} else {
println!("Missing user data for workflow ID {}:", workflow_id);
println!("{:<30}", "Missing User Data ID");
println!("{}", "-".repeat(30));
for user_data_id in &missing_data.user_data {
println!("{:<30}", user_data_id);
}
}
}
Err(e) => {
print_error("listing missing user data", &e);
std::process::exit(1);
}
}
}
}
}