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