smbcloud_cli/project/
mod.rs

1pub mod cli;
2pub mod init;
3
4use self::cli::Commands;
5use crate::cli::CommandResult;
6use anyhow::{anyhow, Result};
7use console::style;
8use dialoguer::{theme::ColorfulTheme, Input};
9use init::process_project_init;
10use log::debug;
11use smbcloud_model::project::{Config, Project};
12use smbcloud_networking::environment::Environment;
13use smbcloud_networking_project::{delete_project, get_all, get_project};
14use spinners::Spinner;
15use std::{fs::OpenOptions, io::Write};
16
17pub async fn process_project(env: Environment, commands: Commands) -> Result<CommandResult> {
18    match commands {
19        Commands::New {} => process_project_init(env).await,
20        Commands::List {} => {
21            let mut spinner = Spinner::new(
22                spinners::Spinners::SimpleDotsScrolling,
23                style("Loading...").green().bold().to_string(),
24            );
25
26            // Get all
27            match get_all(env).await {
28                Ok(projects) => {
29                    spinner.stop_and_persist("✅", "Loaded.".to_owned());
30                    let msg = if projects.is_empty() {
31                        "No projects found.".to_owned()
32                    } else {
33                        "Showing all projects.".to_owned()
34                    };
35                    show_projects(projects);
36                    Ok(CommandResult {
37                        spinner: Spinner::new(
38                            spinners::Spinners::SimpleDotsScrolling,
39                            style("Loading...").green().bold().to_string(),
40                        ),
41                        symbol: "✅".to_owned(),
42                        msg,
43                    })
44                }
45                Err(e) => {
46                    println!("Error: {e:#?}");
47                    Ok(CommandResult {
48                        spinner,
49                        symbol: "😩".to_owned(),
50                        msg: "Failed to get all projects.".to_owned(),
51                    })
52                }
53            }
54        }
55        Commands::Show { id } => {
56            let mut spinner = Spinner::new(
57                spinners::Spinners::SimpleDotsScrolling,
58                style("Loading...").green().bold().to_string(),
59            );
60            // Get Detail
61            match get_project(env, id).await {
62                Ok(project) => {
63                    spinner.stop_and_persist("✅", "Loaded.".to_owned());
64                    let message = format!("Showing project {}.", &project.name);
65                    show_projects(vec![project]);
66                    Ok(CommandResult {
67                        spinner: Spinner::new(
68                            spinners::Spinners::SimpleDotsScrolling,
69                            style("Loading...").green().bold().to_string(),
70                        ),
71                        symbol: "✅".to_owned(),
72                        msg: message,
73                    })
74                }
75                Err(e) => {
76                    spinner.stop_and_persist("😩", "Failed.".to_string());
77                    Err(anyhow!("{e}"))
78                }
79            }
80        }
81        Commands::Delete { id } => {
82            let confirmation = Input::<String>::with_theme(&ColorfulTheme::default())
83                .with_prompt("Are you sure? (y/n)")
84                .interact()
85                .unwrap();
86
87            let mut spinner = Spinner::new(
88                spinners::Spinners::SimpleDotsScrolling,
89                style("Deleting project...").green().bold().to_string(),
90            );
91
92            if confirmation != "y" {
93                return Ok(CommandResult {
94                    spinner,
95                    symbol: "✅".to_owned(),
96                    msg: "Cancelled.".to_string(),
97                });
98            }
99            match delete_project(env, id).await {
100                Ok(_) => {
101                    spinner.stop_and_persist("✅", "Done.".to_string());
102                    Ok(CommandResult {
103                        spinner: Spinner::new(
104                            spinners::Spinners::SimpleDotsScrolling,
105                            style("Loading...").green().bold().to_string(),
106                        ),
107                        symbol: "✅".to_owned(),
108                        msg: "Project has been deleted.".to_string(),
109                    })
110                }
111                Err(e) => {
112                    spinner.stop_and_persist("😩", "Failed.".to_string());
113                    Err(anyhow!("{e}"))
114                }
115            }
116        }
117        Commands::Use { id } => {
118            let project = get_project(env, id).await?;
119
120            let config = Config {
121                current_project: Some(project),
122                current_auth_app: None,
123            };
124
125            let spinner = Spinner::new(
126                spinners::Spinners::SimpleDotsScrolling,
127                style("Loading...").green().bold().to_string(),
128            );
129            match home::home_dir() {
130                Some(path) => {
131                    debug!("{}", path.to_str().unwrap());
132                    let mut file = OpenOptions::new()
133                        .create(true)
134                        .truncate(true)
135                        .write(true)
136                        .open([path.to_str().unwrap(), "/.smb/config.json"].join(""))?;
137                    let json = serde_json::to_string(&config)?;
138                    file.write_all(json.as_bytes())?;
139
140                    Ok(CommandResult {
141                        spinner,
142                        symbol: "✅".to_owned(),
143                        msg: "Use project successful.".to_string(),
144                    })
145                }
146                None => {
147                    let error = anyhow!("Failed to get home directory.");
148                    Err(error)
149                }
150            }
151        }
152    }
153}
154
155// Private functions
156
157fn show_projects(projects: Vec<Project>) {
158    // println!("Projects: {projects:#?}");
159    if projects.is_empty() {
160        return;
161    }
162    println!(
163        "{0: <5} | {1: <20} | {2: <30} | {3: <20} | {4: <20}",
164        "ID", "Name", "Description", "Created at", "Updated at"
165    );
166    for project in projects {
167        println!(
168            "{0: <5} | {1: <20} | {2: <30} | {3: <20} | {4: <20}",
169            project.id,
170            project.name,
171            project.description,
172            project.created_at.date_naive(),
173            project.updated_at.date_naive(),
174        );
175    }
176}