3 files changed
+94
-45
smbpndk-cli/src/project/mod.rs
+89
-40
@@ -5,7 +5,7 @@ use anyhow::{anyhow, Result};
5
use console::style;
6
use dialoguer::{theme::ColorfulTheme, Input};
7
use log::debug;
8
-use smbpndk_model::{CommandResult, Config, ProjectCreate};
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};
@@ -22,9 +22,9 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
22
.interact()
23
.unwrap();
24
25
- let spinner = Spinner::new(
25
+ let mut spinner = Spinner::new(
26
spinners::Spinners::SimpleDotsScrolling,
27
- style("Creating project...").green().bold().to_string(),
27
+ style("Creating a project...").green().bold().to_string(),
28
);
29
30
match create_project(ProjectCreate {
@@ -33,11 +33,17 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
33
})
34
.await
35
{
36
- Ok(_) => Ok(CommandResult {
37
- spinner,
38
- symbol: "✅".to_owned(),
39
- msg: format!("Creating a project {project_name}."),
40
- }),
36
+ Ok(_) => {
37
+ spinner.stop_and_persist("✅", "Done.".to_owned());
38
+ Ok(CommandResult {
39
+ spinner: Spinner::new(
40
+ spinners::Spinners::SimpleDotsScrolling,
41
+ style("Loading...").green().bold().to_string(),
42
+ ),
43
+ symbol: "✅".to_owned(),
44
+ msg: format!("{project_name} has been created."),
45
+ })
46
+ }
47
Err(e) => {
48
println!("Error: {e:#?}");
49
Ok(CommandResult {
@@ -49,7 +55,7 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
55
}
56
}
57
Commands::List {} => {
52
- let spinner = Spinner::new(
58
+ let mut spinner = Spinner::new(
59
spinners::Spinners::SimpleDotsScrolling,
60
style("Loading...").green().bold().to_string(),
61
);
@@ -57,24 +63,20 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
63
// Get all
64
match get_all().await {
65
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
- }
66
+ spinner.stop_and_persist("✅", "Loaded.".to_owned());
67
+ let msg = if projects.is_empty() {
68
+ "No projects found.".to_owned()
69
+ } else {
70
+ "Showing all projects.".to_owned()
71
+ };
72
+ show_projects(projects);
73
Ok(CommandResult {
75
- spinner,
74
+ spinner: Spinner::new(
75
+ spinners::Spinners::SimpleDotsScrolling,
76
+ style("Loading...").green().bold().to_string(),
77
+ ),
78
symbol: "✅".to_owned(),
77
- msg: "Showing all projects.".to_owned(),
79
+ msg,
80
})
81
}
82
Err(e) => {
@@ -88,42 +90,66 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
90
}
91
}
92
Commands::Show { id } => {
91
- let spinner = Spinner::new(
93
+ let mut spinner = Spinner::new(
94
spinners::Spinners::SimpleDotsScrolling,
95
style("Loading...").green().bold().to_string(),
96
);
97
// Get Detail
98
match get_project(id).await {
97
- Ok(_) => Ok(CommandResult {
98
- spinner,
99
- symbol: "✅".to_owned(),
100
- msg: "Showing all projects.".to_owned(),
101
- }),
99
+ Ok(project) => {
100
+ spinner.stop_and_persist("✅", "Loaded.".to_owned());
101
+ let message = format!("Showing project {}.", &project.name);
102
+ show_projects(vec![project]);
103
+ Ok(CommandResult {
104
+ spinner: Spinner::new(
105
+ spinners::Spinners::SimpleDotsScrolling,
106
+ style("Loading...").green().bold().to_string(),
107
+ ),
108
+ symbol: "✅".to_owned(),
109
+ msg: message,
110
+ })
111
+ }
112
Err(e) => {
113
println!("Error: {e:#?}");
114
Ok(CommandResult {
115
spinner,
116
symbol: "😩".to_owned(),
107
- msg: "Failed to get all projects.".to_owned(),
117
+ msg: "Failed to get project.".to_owned(),
118
})
119
}
120
}
121
}
122
Commands::Delete { id } => {
113
- let spinner = Spinner::new(
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
);
117
- match delete_project(id).await {
118
- Ok(_) => Ok(CommandResult {
132
+
133
+ if confirmation != "y" {
134
+ return Ok(CommandResult {
135
spinner,
136
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)
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) => Err(anyhow!("{e}")),
153
}
154
}
155
Commands::Use { id } => {
@@ -162,3 +188,26 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
188
}
189
}
190
}
191
+
192
+// Private functions
193
+
194
+fn show_projects(projects: Vec<Project>) {
195
+ // println!("Projects: {projects:#?}");
196
+ if projects.len() == 0 {
197
+ return;
198
+ }
199
+ println!(
200
+ "{0: <5} | {1: <20} | {2: <30} | {3: <20} | {4: <20}",
201
+ "ID", "Name", "Description", "Created at", "Updated at"
202
+ );
203
+ for project in projects {
204
+ println!(
205
+ "{0: <5} | {1: <20} | {2: <30} | {3: <20} | {4: <20}",
206
+ project.id,
207
+ project.name,
208
+ project.description,
209
+ project.created_at.date_naive(),
210
+ project.updated_at.date_naive(),
211
+ );
212
+ }
213
+}
smbpndk-model/src/lib.rs
+1
@@ -73,6 +73,7 @@ pub struct Config {
73
pub struct Project {
74
pub id: i32,
75
pub name: String,
76
+ pub description: String,
77
#[serde(with = "ar_date_format")]
78
pub created_at: DateTime<Utc>,
79
#[serde(with = "ar_date_format")]
smbpndk-networking-project/src/lib.rs
+4
-5
@@ -1,7 +1,6 @@
1
use anyhow::{anyhow, Result};
2
use log::debug;
3
use reqwest::Client;
4
-
4
use smbpndk_model::{Project, ProjectCreate};
5
use smbpndk_networking::{get_token, smb_base_url_builder};
6
@@ -41,7 +40,7 @@ pub async fn create_project(project: ProjectCreate) -> Result<Project> {
40
match response.status() {
41
reqwest::StatusCode::CREATED => {
42
let project: Project = response.json().await?;
44
- println!("Project created: {project:#?}");
43
+ // println!("Project created: {project:#?}");
44
Ok(project)
45
}
46
_ => Err(anyhow!("Failed to create a project.")),
@@ -53,7 +52,7 @@ pub async fn get_project(id: String) -> Result<Project> {
52
let token = get_token().await.unwrap();
53
54
let response = Client::new()
56
- .get(build_project_url())
55
+ .get(build_project_url_with_id(id))
56
.header("Authorization", token)
57
.send()
58
.await?;
@@ -73,7 +72,7 @@ pub async fn delete_project(id: String) -> Result<()> {
72
let token = get_token().await.unwrap();
73
74
let response = Client::new()
76
- .delete(build_delete_project_url(id))
75
+ .delete(build_project_url_with_id(id))
76
.header("Authorization", token)
77
.send()
78
.await?;
@@ -95,7 +94,7 @@ fn build_project_url() -> String {
94
url_builder.build()
95
}
96
98
-fn build_delete_project_url(id: String) -> String {
97
+fn build_project_url_with_id(id: String) -> String {
98
let mut url_builder = smb_base_url_builder();
99
url_builder.add_route("v1/projects");
100
url_builder.add_route(id.as_str());