pub mod graphql;
use crate::common::{
authorization_headers::authorization_headers,
execute_graphql_request::execute_graphql_request,
fetch_user_id::fetch_user_id,
format_relative_time::format_relative_time,
keyring::keyring,
lengify::lengify,
pagination_list::pagination_list,
print_formatted_error::print_formatted_error,
query_full_id::{query_full_id, QueryType},
};
use crate::projects::list::graphql::team_projects::{team_projects, TeamProjects};
use crate::projects::list::graphql::user_personal_project_team_id::{
user_personal_project_team_id, UserPersonalProjectTeamId,
};
use clap::Args;
use graphql_client::GraphQLQuery;
use reqwest::Client;
use termimad::crossterm::style::Stylize;
#[derive(Args, Debug)]
pub struct ProjectsListArgs {
#[clap(
short,
long,
help = "Team ID (First 4 characters or more are allowed), not required"
)]
id: Option<String>,
#[clap(
short,
long,
help = "Access token, if not specified, the token will be taken from the keychain"
)]
access_token: Option<String>,
}
pub fn list(args: &ProjectsListArgs) {
let access_token = match &args.access_token {
Some(token) => token.clone(),
None => keyring::get("access_token"),
};
let client = Client::new();
let authorization_headers = authorization_headers(&access_token);
let user_id = fetch_user_id(&access_token);
let team_id;
let mut is_personal_project = false;
match &args.id {
Some(id) => {
team_id = query_full_id(QueryType::Teams, id.clone(), &access_token);
}
None => {
let user_personal_project_team_id_error_message = "Personal projects not found";
let personal_team = execute_graphql_request::<
user_personal_project_team_id::Variables,
user_personal_project_team_id::ResponseData,
>(
authorization_headers.clone(),
UserPersonalProjectTeamId::build_query,
&client,
&user_personal_project_team_id_error_message,
user_personal_project_team_id::Variables {
user_id: user_id.clone(),
},
)
.team;
if let Some(team_data) = personal_team.first() {
team_id = team_data.id.clone();
is_personal_project = true;
} else {
print_formatted_error(&user_personal_project_team_id_error_message);
std::process::exit(1);
}
}
}
let projects: Vec<team_projects::TeamProjectsToken> =
execute_graphql_request::<team_projects::Variables, team_projects::ResponseData>(
authorization_headers.clone(),
TeamProjects::build_query,
&client,
&format!("Projects for team '{}' not found.", &team_id),
team_projects::Variables {
id: team_id,
user_id,
},
)
.token;
let mut list = Vec::new();
for project in projects {
let last_usage_time = if let Some(usage_history) = project.usage_history.first() {
match format_relative_time(&usage_history.updated_at.to_string()) {
Ok(relative_time) => relative_time,
Err(_) => {
print_formatted_error("Failed to format last data usage time.");
std::process::exit(1);
}
}
} else {
"never used".to_string().grey()
};
list.push(format!(
"{} {} {} {}",
&project.id.to_string()[..4].green(),
lengify(&project.name),
if is_personal_project {
"".to_string()
} else {
format!(
"{} ({})",
project.owner.name.dark_cyan(),
project.owner.email.dark_cyan()
)
},
last_usage_time.dark_grey()
))
}
pagination_list(
list,
format!(
"Showing projects in {} team",
&team_id.to_string().bold().dark_cyan()
),
"You don't have any projects on this team.",
)
}