smbcloud_cli/project/
mod.rs

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