@smbcloud / cli / commits / cc9a25c

WIP

Seto Elkahfi committed May 13, 2023 at 18:37 UTC cc9a25c70f8a7aa384c07255d3c428dc41b50d5e
6 files changed +72 -21
app-oten/src/handler.rs
+16 -8
@@ -2,30 +2,38 @@ use crate::{cli::Commands, create_oten_app, delete_oten_app, get_oten_app, get_o
2 use anyhow::{anyhow, Result};
3 use console::style;
4 use dialoguer::{theme::ColorfulTheme, Confirm, Input};
5 -use smbpndk_model::{AppCreate, CommandResult};
5 +use smbpndk_model::{
6 + create_params::{self, AppCreate},
7 + CommandResult,
8 +};
9 use smbpndk_utils::{get_config, write_config};
10 use spinners::Spinner;
11
12 pub async fn process_oten_app(commands: Commands) -> Result<CommandResult> {
13 match commands {
14 Commands::New {} => {
15 + let config = get_config().await?;
16 + if config.current_project.is_none() {
17 + return Err(anyhow!(
18 + "No project selected. Please select a project first. Run `smb project use <id>`."
19 + ));
20 + }
21 +
22 let app_name = Input::<String>::with_theme(&ColorfulTheme::default())
23 .with_prompt("App name")
24 .interact()
25 .unwrap();
16 - let description = Input::<String>::with_theme(&ColorfulTheme::default())
17 - .with_prompt("Description")
18 - .interact()
19 - .unwrap();
26
27 let spinner = Spinner::new(
28 spinners::Spinners::SimpleDotsScrolling,
29 style("Creating an Oten app...").green().bold().to_string(),
30 );
31
26 - match create_oten_app(AppCreate {
27 - name: app_name.clone(),
28 - description: description.clone(),
32 + match create_oten_app(create_params::Oten {
33 + oten_app: AppCreate {
34 + name: app_name.clone(),
35 + project_id: config.current_project.unwrap().id,
36 + },
37 })
38 .await
39 {
app-oten/src/lib.rs
+2 -2
@@ -4,7 +4,7 @@ pub mod handler;
4 use anyhow::{anyhow, Result};
5 use log::debug;
6 use reqwest::Client;
7 -use smbpndk_model::{AppCreate, Oten};
7 +use smbpndk_model::{create_params, Oten};
8 use smbpndk_networking::{constants::BASE_URL, get_token};
9
10 async fn get_oten_apps() -> Result<Vec<Oten>> {
@@ -67,7 +67,7 @@ async fn delete_oten_app(id: String) -> Result<()> {
67 }
68 }
69
70 -async fn create_oten_app(oten_app: AppCreate) -> Result<Oten> {
70 +async fn create_oten_app(oten_app: create_params::Oten) -> Result<Oten> {
71 // Get current token
72 let token = get_token().await?;
73
smbpndk-cli/src/project/cli.rs
+1 -4
@@ -23,8 +23,5 @@ pub enum Commands {
23 },
24
25 #[clap(about = "Use project for current CLI session.")]
26 - Use {
27 - #[clap(short, long, required = true)]
28 - id: String,
29 - },
26 + Use {},
27 }
smbpndk-cli/src/project/mod.rs
+18 -5
@@ -2,10 +2,10 @@ pub mod cli;
2
3 use self::cli::Commands;
4 use anyhow::{anyhow, Result};
5 -use console::style;
6 -use dialoguer::{theme::ColorfulTheme, Input};
5 +use console::{style, Term};
6 +use dialoguer::{theme::ColorfulTheme, Input, Select};
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};
@@ -126,8 +126,9 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
126 }
127 }
128 }
129 - Commands::Use { id } => {
130 - let project = get_project(id).await?;
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),
@@ -165,3 +166,15 @@ pub async fn process_project(commands: Commands) -> Result<CommandResult> {
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 +}
smbpndk-model/src/lib.rs
+32 -1
@@ -1,3 +1,5 @@
1 +use std::fmt::Display;
2 +
3 use chrono::{DateTime, Utc};
4 use serde::{Deserialize, Serialize};
5 use spinners::Spinner;
@@ -96,6 +98,21 @@ pub struct AppCreate {
98 pub description: String,
99 }
100
101 +pub mod create_params {
102 + use serde::{Deserialize, Serialize};
103 +
104 + #[derive(Deserialize, Debug, Serialize)]
105 + pub struct Oten {
106 + pub oten_app: AppCreate,
107 + }
108 +
109 + #[derive(Deserialize, Debug, Serialize)]
110 + pub struct AppCreate {
111 + pub name: String,
112 + pub project_id: i32,
113 + }
114 +}
115 +
116 #[derive(Deserialize, Debug, Serialize)]
117 pub struct Config {
118 pub current_project: Option<Project>,
@@ -105,7 +122,7 @@ pub struct Config {
122 pub current_rdb_app: Option<Rdb>,
123 }
124
108 -#[derive(Deserialize, Debug, Serialize)]
125 +#[derive(Deserialize, Debug, Serialize, Clone)]
126 pub struct Project {
127 pub id: i32,
128 pub name: String,
@@ -114,6 +131,20 @@ pub struct Project {
131 #[serde(with = "ar_date_format")]
132 pub updated_at: DateTime<Utc>,
133 }
134 +
135 +impl Display for Project {
136 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 + let id = self.id.to_string();
138 + let name = self.name.to_string();
139 + let created_at = self.created_at.date_naive();
140 + let updated_at = self.updated_at.date_naive();
141 + write!(
142 + f,
143 + "{0: <5} | {1: <20} | {2: <30} | {3: <30}",
144 + id, name, created_at, updated_at
145 + )
146 + }
147 +}
148 #[derive(Serialize, Debug)]
149 pub struct ProjectCreate {
150 pub name: String,
smbpndk-utils/src/lib.rs
+3 -1
@@ -21,7 +21,7 @@ pub fn email_validation(input: &str) -> Result<(), &'static str> {
21 pub async fn get_config() -> Result<Config> {
22 match home::home_dir() {
23 Some(mut path) => {
24 - path.push(".smb/config.json");
24 + path.push(".smb/config");
25 if !path.exists() {
26 let config = Config {
27 current_project: None,
@@ -36,8 +36,10 @@ pub async fn get_config() -> Result<Config> {
36 debug!("Error while reading config file: {}", &e);
37 anyhow!("Error while reading config file. Are you logged in?")
38 })?;
39 + print!("config_string: {:#?}", config_string);
40 let config: Config = serde_json::from_str(&config_string).map_err(|e| {
41 debug!("Error while parsing config: {}", &e);
42 + print!("Error while parsing config: {}", &e);
43 anyhow!("Error while parsing config. Are you logged in?")
44 })?;
45