smbcloud_cli/project/
mod.rs1pub 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 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 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
195fn show_projects(projects: Vec<Project>) {
198 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}