From e7197b50ae9671f2644e9cb4f4c522d21e6590c6 Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Sun, 21 Apr 2024 18:18:28 -0400 Subject: [PATCH] feat!: finish postman imports, improve UX around stored requests --- .gitignore | 1 - README.md | 2 +- imgs/saved_request.png | Bin 24859 -> 73538 bytes src/app.rs | 45 ++++++++- src/database/db.rs | 159 +++++++++++++++++++++++------- src/database/postman.rs | 103 ++++++++++--------- src/display/inputopt.rs | 6 ++ src/display/menuopts.rs | 13 +-- src/display/mod.rs | 11 +-- src/request/curl.rs | 115 +++++++++++++++++++-- src/request/mod.rs | 2 - src/screens/collections.rs | 9 +- src/screens/input/input_screen.rs | 68 +++++++++---- src/screens/more_flags.rs | 10 +- src/screens/render.rs | 4 +- src/screens/saved_commands.rs | 116 +++++++++++++++++----- src/screens/screen.rs | 10 +- test_collection.json | 40 ++++++++ 18 files changed, 537 insertions(+), 177 deletions(-) create mode 100644 test_collection.json diff --git a/.gitignore b/.gitignore index 69be759..d7da0b5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ .vs testapi.txt /postman -*.json diff --git a/README.md b/README.md index 93f56d0..6930149 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- +
diff --git a/imgs/saved_request.png b/imgs/saved_request.png index edee01b9e119dacac5000cb48036135b03b95018..8dc074091d1b96ebbcd28776bfe0415178f87fdb 100644 GIT binary patch literal 73538 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 EUr4&>!gCZAWGqld)_mT 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 z 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 Aj{pDw diff --git a/src/app.rs b/src/app.rs index c261732..be037e8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -67,12 +67,18 @@ impl<'a> Default for App<'a> { state: None, current_screen: Screen::Home, response: None, - db: Box::new(DB::new().unwrap()), + db: Box::new(DB::new().expect("Failed to create database")), } } } impl<'a> App<'a> { + fn new_test_db() -> Self { + Self { + db: Box::new(DB::new_test().expect("Failed to create database")), + ..Default::default() + } + } pub fn new() -> Self { Self::default() } @@ -185,7 +191,7 @@ impl<'a> App<'a> { } Some( Screen::InputMenu(_) - | Screen::CmdMenu(_) + | Screen::CmdMenu { .. } | Screen::ColMenu(_) | Screen::KeysMenu(_), ) => self.go_back_screen(), @@ -335,8 +341,9 @@ impl<'a> App<'a> { match collection { Ok(collection) => { let name = collection.info.name.clone(); + let description = collection.info.description.clone(); let cmds: Vec = collection.into(); - self.db.add_collection(&name, cmds.as_slice()) + self.db.add_collection(&name, &description, cmds.as_slice()) } Err(e) => Err(e.into()), } @@ -375,7 +382,7 @@ impl<'a> App<'a> { pub fn delete_item(&mut self, ind: i32) -> Result<(), rusqlite::Error> { match self.current_screen { - Screen::CmdMenu(_) => self.db.as_ref().delete_command(ind), + Screen::CmdMenu { .. } => self.db.as_ref().delete_command(ind), Screen::KeysMenu(_) => self.db.as_ref().delete_key(ind), Screen::ViewSavedCollections => self.db.as_ref().delete_collection(ind), _ => Ok(()), @@ -453,7 +460,7 @@ impl<'a> App<'a> { #[cfg(test)] pub mod tests { use super::App; - use crate::request::curl::AuthKind; + use crate::request::curl::{AuthKind, Curl}; #[test] fn test_basic_get_method() { @@ -767,4 +774,32 @@ pub mod tests { std::fs::remove_file("test.txt").unwrap(); let _ = std::fs::remove_file("cookie-jar"); } + #[test] + fn test_import_postman_collection() { + let mut app = App::new_test_db(); + let path = "test_collection.json"; + let res = app.import_postman_collection(path); + let file = std::fs::File::open(path).unwrap(); + let collection: crate::database::postman::PostmanCollection = + serde_json::from_reader(file).unwrap(); + assert_eq!(collection.info.name.clone().as_str(), "Test Collection"); + let cmds: Vec = collection.into(); + let db = app.db.as_ref(); + let collections = db.get_collections().unwrap(); + let commands = db.get_commands(None).unwrap(); + let command = commands[0].clone(); + let curl: Curl = serde_json::from_str(command.get_curl_json()).unwrap(); + assert!(res.is_ok()); + assert_eq!(collections.len(), 1); + assert_eq!(commands.len(), cmds.len()); + assert_eq!(curl.get_method().to_string(), "POST"); + assert_eq!(curl.get_url(), "https://echo.getpostman.com/post"); + assert_eq!( + curl.headers, + Some(vec![ + String::from("Content-Type: application/json"), + String::from("Host: echo.getpostman.com") + ]) + ); + } } diff --git a/src/database/db.rs b/src/database/db.rs index 1338203..2d50a0a 100644 --- a/src/database/db.rs +++ b/src/database/db.rs @@ -11,16 +11,20 @@ use std::{ #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] pub struct SavedCommand { - id: i32, + pub id: i32, command: String, + pub description: Option, + pub label: Option, curl_json: String, - collection_id: Option, + pub collection_id: Option, + pub collection_name: Option, } #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] pub struct SavedCollection { id: i32, - name: String, + pub name: String, + pub description: Option, } impl Display for SavedCollection { @@ -42,6 +46,23 @@ pub struct DB { } impl DB { + pub fn new_test() -> Result { + let conn = Connection::open_in_memory()?; + conn.execute( + "CREATE TABLE commands (id INTEGER PRIMARY KEY, command TEXT, label TEXT, description TEXT, curl_json TEXT, collection_id INT);", + params![], + )?; + conn.execute( + "CREATE TABLE keys (id INTEGER PRIMARY KEY, key TEXT, label TEXT);", + params![], + )?; + conn.execute( + "CREATE TABLE collections (id INTEGER PRIMARY KEY, name TEXT, description TEXT);", + params![], + )?; + Ok(DB { conn }) + } + pub fn new() -> Result { let mut _path: PathBuf = PathBuf::new(); if std::env::var("CUTE_DB_PATH").is_ok() { @@ -79,7 +100,7 @@ impl DB { conn.execute("BEGIN;", params![])?; // collection_id needs to be nullable conn.execute( - "CREATE TABLE IF NOT EXISTS commands (id INTEGER PRIMARY KEY, command TEXT, curl_json TEXT, collection_id INT NULL);", + "CREATE TABLE IF NOT EXISTS commands (id INTEGER PRIMARY KEY, label TEXT, description TEXT, command TEXT, curl_json TEXT, collection_id INT);", params![], )?; @@ -89,7 +110,7 @@ impl DB { )?; conn.execute( - "CREATE TABLE IF NOT EXISTS collections (id INTEGER PRIMARY KEY, name TEXT);", + "CREATE TABLE IF NOT EXISTS collections (id INTEGER PRIMARY KEY, name TEXT, description TEXT);", params![], )?; @@ -106,6 +127,18 @@ impl DB { Ok(()) } + pub fn set_collection_description( + &self, + id: i32, + description: &str, + ) -> Result<(), rusqlite::Error> { + let mut stmt = self + .conn + .prepare("UPDATE collections SET description = ? WHERE id = ?")?; + stmt.execute(params![description, id])?; + Ok(()) + } + pub fn get_number_of_commands_in_collection(&self, id: i32) -> Result { let mut stmt = self .conn @@ -115,45 +148,48 @@ impl DB { } #[rustfmt::skip] - pub fn add_collection(&self, name: &str, commands: &[SavedCommand]) -> Result<(), Box> { + pub fn add_collection(&self, name: &str, desc: &str, commands: &[SavedCommand]) -> Result<(), Box> { let mut stmt = self .conn - .prepare("INSERT INTO collections (name) VALUES (?1)")?; - let _ = stmt.execute(params![name])?; - let mut stmt = self - .conn - .prepare("SELECT id FROM collections WHERE name = ?1")?; - let id: i32 = stmt.query_row(params![name], |row| row.get(0))?; + .prepare("INSERT INTO collections (name, description) VALUES (?1, ?2)")?; + let id = stmt.insert(params![name, desc])?; for command in commands { - self.add_command_from_collection(&command.command, &command.curl_json, id)?; + self.add_command_from_collection(&command.command, command.label.as_deref(), command.description.as_deref(), &command.curl_json, id as i32)?; } Ok(()) } pub fn get_command_by_id(&self, id: i32) -> Result { - let mut stmt = self - .conn - .prepare("SELECT id, command, curl_json, collection_id from commands WHERE id = ?1")?; + let mut stmt = self.conn.prepare( + "SELECT cmd.id, cmd.command, cmd.label, cmd.description, cmd.curl_json, cmd.collection_id, col.name as collection_name FROM commands cmd LEFT JOIN collections col ON cmd.collection_id = col.id WHERE cmd.id = ?" + )?; stmt.query_row(params![id], |row| { Ok(SavedCommand { id: row.get(0)?, command: row.get(1)?, - curl_json: row.get(2)?, - collection_id: row.get(3)?, + label: row.get(2)?, + description: row.get(3)?, + curl_json: row.get(4)?, + collection_id: row.get(5)?, + collection_name: row.get(6)?, }) }) } - pub fn get_collection_by_id(&self, id: i32) -> Result { + pub fn get_collection_by_id(&self, id: i32) -> Result { let mut stmt = self .conn - .prepare("SELECT id, name FROM collections WHERE id = ?")?; - let collection = stmt.query_row(params![id], |row| { - Ok(SavedCollection { - id: row.get(0)?, - name: row.get(1)?, + .prepare("SELECT id, name, description FROM collections WHERE id = ?") + .map_err(|_| "No Collection".to_string())?; + let collection = stmt + .query_row(params![id], |row| { + Ok(SavedCollection { + id: row.get(0)?, + name: row.get(1)?, + description: row.get(2)?, + }) }) - })?; + .map_err(|_| ("No Collection".to_string()))?; Ok(collection) } @@ -166,11 +202,14 @@ impl DB { } pub fn get_collections(&self) -> Result> { - let mut stmt = self.conn.prepare("SELECT id, name FROM collections")?; + let mut stmt = self + .conn + .prepare("SELECT id, name, description FROM collections")?; let rows = stmt.query_map(params![], |row| { Ok(SavedCollection { id: row.get(0)?, name: row.get(1)?, + description: row.get(2)?, }) })?; Ok(rows @@ -188,25 +227,55 @@ impl DB { &self, command: &str, json_str: String, - col_name: Option, + col_id: Option, ) -> Result<(), rusqlite::Error> { let mut stmt = self.conn.prepare( "INSERT INTO commands (command, curl_json, collection_id) VALUES (?1, ?2, ?3)", )?; - let _ = stmt.execute(params![command, &json_str, col_name])?; + let _ = stmt.execute(params![command, &json_str, col_id])?; Ok(()) } + pub fn set_command_description( + &self, + id: i32, + description: &str, + ) -> Result, rusqlite::Error> { + let mut stmt = self + .conn + .prepare("UPDATE commands SET description = ?1 WHERE id = ?2")?; + stmt.execute(params![description, id])?; + let mut stmt = self + .conn + .prepare("SELECT collection_id FROM commands WHERE id = ?")?; + let collection_id: Option = stmt.query_row(params![id], |row| row.get(0))?; + Ok(collection_id) + } + + pub fn set_command_label(&self, id: i32, label: &str) -> Result, rusqlite::Error> { + let mut stmt = self + .conn + .prepare("UPDATE commands SET label = ?1 WHERE id = ?2")?; + stmt.execute(params![label, id])?; + let mut stmt = self + .conn + .prepare("SELECT collection_id FROM commands WHERE id = ?")?; + let collection_id: Option = stmt.query_row(params![id], |row| row.get(0))?; + Ok(collection_id) + } + pub fn add_command_from_collection( &self, command: &str, + label: Option<&str>, + desc: Option<&str>, json_str: &str, collection_id: i32, ) -> Result<(), rusqlite::Error> { let mut stmt = self.conn.prepare( - "INSERT INTO commands (command, curl_json, collection_id) VALUES (?1, ?2, ?3)", + "INSERT INTO commands (command, label, description, curl_json, collection_id) VALUES (?1, ?2, ?3, ?4, ?5)", )?; - let _ = stmt.execute(params![command, &json_str, collection_id])?; + let _ = stmt.execute(params![command, label, desc, json_str, collection_id])?; Ok(()) } @@ -236,26 +305,32 @@ impl DB { if let Some(id) = id { let mut stmt = self .conn - .prepare("SELECT id, command, curl_json, collection_id FROM commands WHERE collection_id = ?")?; + .prepare("SELECT cmd.id, cmd.command, cmd.label, cmd.description, cmd.curl_json, cmd.collection_id, col.name as collection_name FROM commands cmd LEFT JOIN collections col ON cmd.collection_id = col.id WHERE cmd.collection_id = ?")?; let rows = stmt.query_map(params![id], |row| { Ok(SavedCommand { id: row.get(0)?, command: row.get(1)?, - curl_json: row.get(2)?, - collection_id: row.get(3)?, + label: row.get(2)?, + description: row.get(3)?, + curl_json: row.get(4)?, + collection_id: row.get(5)?, + collection_name: row.get(6)?, }) })?; - return Ok(rows.into_iter().map(|row| row.unwrap()).collect()); + return Ok(rows.into_iter().filter_map(|row| row.ok()).collect()); } let mut stmt = self .conn - .prepare("SELECT id, command, curl_json FROM commands")?; + .prepare("SELECT cmd.id, cmd.command, cmd.label, cmd.description, cmd.curl_json, cmd.collection_id, col.name FROM commands cmd LEFT JOIN collections col ON cmd.collection_id = col.id")?; let rows = stmt.query_map(params![], |row| { Ok(SavedCommand { id: row.get(0)?, command: row.get(1)?, - curl_json: row.get(2)?, - collection_id: None, + label: row.get(2)?, + description: row.get(3)?, + curl_json: row.get(4)?, + collection_id: row.get(5)?, + collection_name: row.get(6)?, }) })?; let mut commands = Vec::new(); @@ -328,11 +403,19 @@ impl SavedCommand { Ok(serde_json::to_string(&self).expect("Failed to serialize")) } - pub fn new(command: &str, curl_json: &str, collection_id: Option) -> Self { + pub fn new( + command: &str, + label: Option, + description: Option, + curl_json: &str, + collection_id: Option, + ) -> Self { SavedCommand { command: command.to_string(), + label, curl_json: curl_json.to_string(), collection_id, + description, ..Default::default() } } diff --git a/src/database/postman.rs b/src/database/postman.rs index 191f4f1..faa4aa6 100644 --- a/src/database/postman.rs +++ b/src/database/postman.rs @@ -1,8 +1,8 @@ use super::db::SavedCommand; -use crate::request::curl::Curl; +use crate::request::curl::{Curl, Method}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::collections::HashMap; +use std::{collections::HashMap, str::FromStr}; #[derive(Serialize, Debug, Deserialize)] pub struct PostmanCollection { @@ -13,41 +13,42 @@ pub struct PostmanCollection { impl From for Vec { fn from(collection: PostmanCollection) -> Vec { let mut saved_commands = Vec::new(); - let mut curl_cmd = Curl::new(); collection.item.iter().for_each(|item| { + let mut curl_cmd = Curl::new_serializing(); + let mut cmd_name: Option = None; + let mut description: Option = None; + if let Some(name) = item.get("name") { + if let Some(name) = name.as_str() { + cmd_name = Some(name.to_string()); + } + } if let Some(request) = item.get("request") { if let Some(request) = request.as_str() { // this means its a get request curl_cmd.set_url(request); curl_cmd.set_get_method(); } else if let Some(request) = request.as_object() { - if let Some(method) = request.get("method") { - if let Some(method) = method.as_str() { - match method { - "GET" => { - curl_cmd.set_get_method(); - } - "POST" => { - curl_cmd.set_post_method(); - } - "PUT" => { - curl_cmd.set_put_method(); - } - "DELETE" => { - curl_cmd.set_delete_method(); - } - "PATCH" => { - curl_cmd.set_patch_method(); - } - "HEAD" => { - curl_cmd.set_head_method(); - } - _ => { - curl_cmd.set_get_method(); + if let Some(desc) = request.get("description") { + if let Some(desc) = desc.as_str() { + description = Some(desc.to_string()); + } + } + if let Some(url) = request.get("url") { + if let Some(str_url) = url.as_str() { + curl_cmd.set_url(str_url); + } else if let Some(url) = url.as_object() { + if let Some(raw) = url.get("raw") { + if let Some(raw_str) = raw.as_str() { + curl_cmd.set_url(raw_str); } } } } + if let Some(method) = request.get("method") { + if let Some(method) = method.as_str() { + curl_cmd.set_method(Method::from_str(method).unwrap_or_default()); + } + } if let Some(headers) = request.get("header") { if let Some(headers) = headers.as_array() { headers.iter().for_each(|hdr| { @@ -143,37 +144,40 @@ impl From for Vec { } } } - } else if let Some(url) = request.get("url") { - if let Some(url) = url.as_object() { - if let Some(url) = url.get("raw") { - if let Some(url) = url.as_str() { - curl_cmd.set_url(url); - } - } - } - } - if let Some(cookie) = request.get("cookie") { - if let Some(cookie) = cookie.as_array() { - cookie.iter().for_each(|ck| { - if let Some(ck) = ck.as_object() { - if let Some(key) = ck.get("key") { - if let Some(key) = key.as_str() { - if let Some(value) = ck.get("value") { - if let Some(value) = value.as_str() { - curl_cmd.add_cookie(&format!("{}: {}", key, value)); + if let Some(cookie) = request.get("cookie") { + if let Some(cookie) = cookie.as_array() { + cookie.iter().for_each(|ck| { + if let Some(ck) = ck.as_object() { + if let Some(key) = ck.get("key") { + if let Some(key) = key.as_str() { + if let Some(value) = ck.get("value") { + if let Some(value) = value.as_str() { + curl_cmd + .add_cookie(&format!("{}: {}", key, value)); + } } } } } - } - }); + }); + } } } } + if cmd_name.is_none() { + cmd_name = Some(String::from(curl_cmd.get_url())); + } + let cmd = curl_cmd.get_command_string(); + let curl_json: String = serde_json::to_string(&curl_cmd).unwrap_or_default(); + saved_commands.push(SavedCommand::new( + &cmd, + cmd_name, + description, + &curl_json, + None, + )); }); - let cmd = curl_cmd.get_command_string(); - let curl_json: String = serde_json::to_string(&curl_cmd).unwrap_or_default(); - saved_commands.push(SavedCommand::new(&cmd, &curl_json, None)); + saved_commands } } @@ -182,4 +186,5 @@ impl From for Vec { pub struct Info { pub name: String, schema: String, + pub description: String, } diff --git a/src/display/inputopt.rs b/src/display/inputopt.rs index ba437c3..f5a116b 100644 --- a/src/display/inputopt.rs +++ b/src/display/inputopt.rs @@ -26,6 +26,9 @@ pub enum InputOpt { CaPath, CaCert, KeyLabel(i32), + CmdLabel(i32), + CmdDescription(i32), + CollectionDescription(i32), ImportCollection, RenameCollection(i32), RequestError(String), @@ -70,6 +73,9 @@ impl Display for InputOpt { InputOpt::Method(method) => write!(f, "| Method: {}", method), InputOpt::CookieJar => write!(f, "| Cookie Jar"), InputOpt::AlertMessage(msg) => write!(f, "| Alert: {}", msg), + InputOpt::CmdLabel(_) => write!(f, "| Command Label"), + InputOpt::CmdDescription(_) => write!(f, "| Command Description"), + InputOpt::CollectionDescription(_) => write!(f, "| Collection Description"), } } } diff --git a/src/display/menuopts.rs b/src/display/menuopts.rs index 3b60906..a18bef8 100644 --- a/src/display/menuopts.rs +++ b/src/display/menuopts.rs @@ -70,7 +70,6 @@ pub const CUTE_LOGO2: &str = " pub const DISPLAY_OPT_VERBOSE: &str = " Verbose"; pub const DISPLAY_OPT_COMMAND_SAVED: &str = " Request will be saved  "; pub const DISPLAY_OPT_HEADERS: &str = " Response headers included 󱈝 "; -pub const DISPLAY_OPT_PROGRESS_BAR: &str = " Enable Progress Bar 󰦖 "; pub const DISPLAY_OPT_FAIL_ON_ERROR: &str = " Fail on error  "; pub const DISPLAY_OPT_TOKEN_SAVED: &str = " Token will be saved  "; pub const DISPLAY_OPT_FOLLOW_REDIRECTS: &str = " Follow redirects 󱀀 "; @@ -107,10 +106,12 @@ pub const SAVE_AUTH_ERROR: &str = pub const VALID_COMMAND_ERROR: &str = "Error: Invalid command.\n You must add either a URL or Unix Socket to execute a command"; -pub const CMD_MENU_OPTIONS: [&str; 4] = [ +pub const CMD_MENU_OPTIONS: [&str; 6] = [ "Execute  ", + "Add a label 󰈮 ", + "Add a description 󰈮 ", "Delete  ", - "Copy to Clipboard 󰅎 ", + "Copy CLI command to clipboard 󰅎 ", "Cancel  ", ]; pub const KEY_MENU_OPTIONS: [&str; 4] = [ @@ -132,8 +133,9 @@ pub const MAIN_MENU_OPTIONS: [&str; 4] = [ "View or Import Postman Collections", "View Saved API keys 󱂛  ", ]; -pub const COLLECTION_ALERT_MENU_OPTS: [&str; 4] = [ +pub const COLLECTION_ALERT_MENU_OPTS: [&str; 5] = [ "View Requests in this collection", + "Add a description", "Rename this collection", "Delete this collection", "Cancel", @@ -189,7 +191,7 @@ pub const AUTHENTICATION_MENU_OPTIONS: [&str; 6] = [ "Ntlm", "SPNEGO", ]; -pub const MORE_FLAGS_MENU: [&str; 12] = [ +pub const MORE_FLAGS_MENU: [&str; 11] = [ "Follow Redirects 󱀀 ", "Specify Max redirects 󱀀 ", "Enable HTTP Proxy-Tunnel 󱠾 ", @@ -197,7 +199,6 @@ pub const MORE_FLAGS_MENU: [&str; 12] = [ "Specify Referrer 󰆽 ", "Specify SSL Certificate path 󰄤 ", "Request Certificate Info 󰄤 ", - "Add Progress Bar 󰦖 ", "Fail on Error  ", "Match wildcard 󰛄 ", "Specify User-Agent 󰖟 ", diff --git a/src/display/mod.rs b/src/display/mod.rs index aff07cd..c1f15f9 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -5,10 +5,9 @@ use self::menuopts::{ DISPLAY_OPT_COMMAND_SAVED, DISPLAY_OPT_CONTENT_HEADERS, DISPLAY_OPT_COOKIE, DISPLAY_OPT_COOKIE_JAR, DISPLAY_OPT_FAIL_ON_ERROR, DISPLAY_OPT_FOLLOW_REDIRECTS, DISPLAY_OPT_HEADERS, DISPLAY_OPT_MATCH_WILDCARD, DISPLAY_OPT_MAX_REDIRECTS, - DISPLAY_OPT_OUTFILE, DISPLAY_OPT_PROGRESS_BAR, DISPLAY_OPT_PROXY_TUNNEL, DISPLAY_OPT_REFERRER, - DISPLAY_OPT_TCP_KEEPALIVE, DISPLAY_OPT_TOKEN_SAVED, DISPLAY_OPT_UNIX_SOCKET, - DISPLAY_OPT_UNRESTRICTED_AUTH, DISPLAY_OPT_UPLOAD, DISPLAY_OPT_URL, DISPLAY_OPT_USERAGENT, - DISPLAY_OPT_VERBOSE, + DISPLAY_OPT_OUTFILE, DISPLAY_OPT_PROXY_TUNNEL, DISPLAY_OPT_REFERRER, DISPLAY_OPT_TCP_KEEPALIVE, + DISPLAY_OPT_TOKEN_SAVED, DISPLAY_OPT_UNIX_SOCKET, DISPLAY_OPT_UNRESTRICTED_AUTH, + DISPLAY_OPT_UPLOAD, DISPLAY_OPT_URL, DISPLAY_OPT_USERAGENT, DISPLAY_OPT_VERBOSE, }; use crate::request::curl::AuthKind; use std::fmt::{Display, Formatter}; @@ -62,7 +61,6 @@ pub enum AppOptions { CookiePath(String), EnableHeaders, ContentHeaders(HeaderKind), - ProgressBar, FailOnError, ProxyTunnel, CaPath(String), @@ -100,7 +98,6 @@ impl AppOptions { Self::FollowRedirects => "-L".to_string(), Self::UnixSocket(ref socket) => format!("--unix-socket {socket}"), Self::MatchWildcard => "-g".to_string(), - Self::ProgressBar => "--progress-bar".to_string(), Self::Auth(ref kind) => match kind { AuthKind::Basic(ref login) => { format!("-u {login}") @@ -131,7 +128,6 @@ impl AppOptions { self, Self::Verbose | Self::EnableHeaders - | Self::ProgressBar | Self::FailOnError | Self::ProxyTunnel | Self::CertInfo @@ -215,7 +211,6 @@ impl AppOptions { } AppOptions::NewCookie(cookie) => format!("{}{}", DISPLAY_OPT_COOKIE, cookie.clone()), AppOptions::EnableHeaders => DISPLAY_OPT_HEADERS.to_string(), - AppOptions::ProgressBar => String::from(DISPLAY_OPT_PROGRESS_BAR), AppOptions::FailOnError => String::from(DISPLAY_OPT_FAIL_ON_ERROR), AppOptions::ProxyTunnel => DISPLAY_OPT_PROXY_TUNNEL.to_string(), AppOptions::UserAgent(ua) => format!("{}{}", DISPLAY_OPT_USERAGENT, ua), diff --git a/src/request/curl.rs b/src/request/curl.rs index d14f7e5..67d89d1 100644 --- a/src/request/curl.rs +++ b/src/request/curl.rs @@ -42,15 +42,15 @@ pub struct Curl { auth: AuthKind, // The final cli command string cmd: String, - headers: Option>, + pub headers: Option>, url: String, - // Build this on the App struct and pass it here to store for serialization pub opts: Vec, resp: Option, upload_file: Option, outfile: Option, // Whether to save the (command, auth/key) to DB after execution save: (bool, bool), + ser: bool, } impl Default for CurlHandler { @@ -143,6 +143,7 @@ impl Clone for Curl { upload_file: self.upload_file.clone(), outfile: self.outfile.clone(), save: self.save, + ser: self.ser, } } } @@ -159,6 +160,7 @@ impl PartialEq for Curl { && self.upload_file == other.upload_file && self.outfile == other.outfile && self.save == other.save + && self.ser == other.ser } } @@ -218,6 +220,7 @@ impl Default for Curl { upload_file: None, outfile: None, save: (false, false), + ser: false, } } } @@ -225,6 +228,12 @@ impl Curl { pub fn new() -> Self { Self::default() } + pub fn new_serializing() -> Self { + Self { + ser: true, + ..Self::default() + } + } pub fn get_url(&self) -> &str { &self.url } @@ -280,6 +289,10 @@ impl Curl { } pub fn set_url(&mut self, url: &str) { + if self.ser { + // if we're serializing, we need to store the URL in the opts + self.opts.push(AppOptions::URL(url.to_string())); + } self.url = String::from(url.trim()); self.curl.url(url).unwrap(); } @@ -293,13 +306,22 @@ impl Curl { } pub fn set_cookie_path(&mut self, path: &str) { + if self.ser { + self.opts.push(AppOptions::CookieJar(path.to_string())); + } self.curl.cookie_file(path).unwrap(); } pub fn set_cookie_jar(&mut self, path: &str) { + if self.ser { + self.opts.push(AppOptions::CookieJar(path.to_string())); + } self.curl.cookie_jar(path).unwrap(); } pub fn reset_cookie_session(&mut self) { + if self.ser { + self.opts.push(AppOptions::NewCookieSession); + } self.curl.cookie_session(true).unwrap(); } @@ -389,6 +411,9 @@ impl Curl { } pub fn set_auth(&mut self, auth: AuthKind) { + if self.ser { + self.opts.push(AppOptions::Auth(auth.clone())); + } match auth { AuthKind::Basic(ref info) => self.set_basic_auth(info), AuthKind::Ntlm => self.set_ntlm_auth(), @@ -412,34 +437,51 @@ impl Curl { } pub fn set_cert_info(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::CertInfo); + } self.curl.certinfo(opt).unwrap(); } pub fn set_referrer(&mut self, referrer: &str) { + if self.ser { + self.opts.push(AppOptions::Referrer(String::from(referrer))); + } self.curl.referer(referrer).unwrap(); } pub fn set_proxy_tunnel(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::ProxyTunnel); + } self.curl.http_proxy_tunnel(opt).unwrap(); } pub fn set_verbose(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::Verbose); + } self.curl.verbose(opt).unwrap(); } pub fn set_fail_on_error(&mut self, fail: bool) { + if self.ser { + self.opts.push(AppOptions::FailOnError); + } self.curl.fail_on_error(fail).unwrap(); } pub fn set_unix_socket(&mut self, socket: &str) { + if self.ser { + self.opts.push(AppOptions::UnixSocket(String::from(socket))); + } self.curl.unix_socket(socket).unwrap(); } - pub fn enable_progress_bar(&mut self, on: bool) { - self.curl.progress(on).unwrap(); - } - pub fn set_content_header(&mut self, kind: &HeaderKind) { + if self.ser { + self.opts.push(AppOptions::ContentHeaders(kind.clone())); + } if let Some(ref mut headers) = self.headers { headers.push(kind.to_string()); } else { @@ -452,6 +494,9 @@ impl Curl { } pub fn add_headers(&mut self, headers: &str) { + if self.ser { + self.opts.push(AppOptions::Headers(headers.to_string())); + } if self.headers.is_some() { self.headers.as_mut().unwrap().push(headers.to_string()); } else { @@ -476,52 +521,82 @@ impl Curl { } } pub fn match_wildcard(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::MatchWildcard); + } self.curl.wildcard_match(opt).unwrap(); } pub fn set_unrestricted_auth(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::UnrestrictedAuth); + } self.curl.unrestricted_auth(opt).unwrap(); } pub fn set_user_agent(&mut self, ua: &str) { + if self.ser { + self.opts.push(AppOptions::UserAgent(ua.to_string())); + } self.curl.useragent(ua).unwrap(); } pub fn set_max_redirects(&mut self, redirects: usize) { + if self.ser { + self.opts.push(AppOptions::MaxRedirects(redirects)); + } self.curl .max_redirections(redirects as u32) .unwrap_or_default(); } pub fn set_ca_path(&mut self, ca_path: &str) { + if self.ser { + self.opts.push(AppOptions::CaPath(ca_path.to_string())); + } self.curl.cainfo(ca_path).unwrap_or_default(); } pub fn set_tcp_keepalive(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::TcpKeepAlive); + } self.curl.tcp_keepalive(opt).unwrap_or_default(); } pub fn set_request_body(&mut self, body: &str) { + if self.ser { + self.opts.push(AppOptions::RequestBody(body.to_string())); + } + self.opts.push(AppOptions::RequestBody(body.to_string())); self.curl .post_fields_copy(body.as_bytes()) .unwrap_or_default(); } pub fn set_follow_redirects(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::FollowRedirects); + } self.curl.follow_location(opt).unwrap_or_default(); } pub fn add_cookie(&mut self, cookie: &str) { + if self.ser { + self.opts.push(AppOptions::NewCookie(cookie.to_string())); + } self.curl.cookie(cookie).unwrap_or_default(); } pub fn set_upload_file(&mut self, file: &str) { + if self.ser { + self.opts.push(AppOptions::UploadFile(file.to_string())); + } self.upload_file = Some(file.to_string()); self.curl.upload(true).unwrap_or_default(); } pub fn write_output(&mut self) -> Result<(), std::io::Error> { - println!("{}", self.outfile.as_ref().unwrap().clone()); match self.outfile { Some(ref mut outfile) => { let mut file = match std::fs::File::create(outfile) { @@ -546,6 +621,9 @@ impl Curl { } } pub fn enable_response_headers(&mut self, opt: bool) { + if self.ser { + self.opts.push(AppOptions::EnableHeaders); + } self.curl.show_header(opt).unwrap_or_default(); } @@ -555,6 +633,7 @@ impl Curl { } pub fn easy_from_opts(&mut self) { + self.ser = true; self.build_command_string(); self.curl.url(&self.url).unwrap(); self.apply_method(); @@ -563,11 +642,18 @@ impl Curl { self.add_option(opt); } } + pub fn set_any_auth(&mut self) { + if self.ser { + self.opts.push(AppOptions::Auth(AuthKind::None)); + } let _ = self.curl.http_auth(&Auth::new()); } pub fn set_basic_auth(&mut self, login: &str) { + if self.ser { + self.opts.push(AppOptions::Auth(AuthKind::Basic(login.to_string()))); + } self.auth = AuthKind::Basic(String::from(login)); } @@ -577,14 +663,23 @@ impl Curl { } pub fn set_digest_auth(&mut self, login: &str) { + if self.ser { + self.opts.push(AppOptions::Auth(AuthKind::Digest(login.to_string()))); + } self.auth = AuthKind::Digest(String::from(login)); } pub fn set_aws_sigv4_auth(&mut self) { + if self.ser { + self.opts.push(AppOptions::Auth(AuthKind::AwsSigv4)); + } self.auth = AuthKind::AwsSigv4; } pub fn set_spnego_auth(&mut self) { + if self.ser { + self.opts.push(AppOptions::Auth(AuthKind::Spnego)); + } self.auth = AuthKind::Spnego; } @@ -627,6 +722,9 @@ impl Curl { } pub fn show_headers(&mut self) { + if self.ser { + self.opts.push(AppOptions::EnableHeaders); + } self.curl.show_header(true).unwrap(); } @@ -669,6 +767,7 @@ impl Curl { } pub fn url_encode(&mut self, data: &str) { - self.url = self.curl.url_encode(data.as_bytes()); + let encoded = self.curl.url_encode(data.as_bytes()); + self.opts.push(AppOptions::RequestBody(encoded)); } } diff --git a/src/request/mod.rs b/src/request/mod.rs index b9a4765..9327381 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -18,7 +18,6 @@ impl ExecuteOption for Curl { AppOptions::Outfile(ref file) => self.set_outfile(file), AppOptions::UploadFile(ref file) => self.set_upload_file(file), AppOptions::UnixSocket(ref file) => self.set_unix_socket(file), - AppOptions::ProgressBar => self.enable_progress_bar(true), AppOptions::FailOnError => self.set_fail_on_error(true), AppOptions::Verbose => self.set_verbose(true), AppOptions::Response(ref resp) => self.set_response(resp), @@ -51,7 +50,6 @@ impl ExecuteOption for Curl { AppOptions::Outfile(_) => self.set_outfile(""), AppOptions::UploadFile(_) => self.set_upload_file(""), AppOptions::UnixSocket(_) => self.set_unix_socket(""), - AppOptions::ProgressBar => self.enable_progress_bar(false), AppOptions::FailOnError => self.set_fail_on_error(false), AppOptions::Verbose => self.set_verbose(false), AppOptions::Response(_) => self.set_response(""), diff --git a/src/screens/collections.rs b/src/screens/collections.rs index a81e269..61117a6 100644 --- a/src/screens/collections.rs +++ b/src/screens/collections.rs @@ -137,12 +137,15 @@ pub fn handle_collection_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i id: Some(cmd), opt: None, }), + Some(1) => app.goto_screen(&Screen::SavedCollections(Some( + InputOpt::CollectionDescription(selected.get_id()), + ))), // Rename Collection - Some(1) => app.goto_screen(&Screen::SavedCollections(Some(InputOpt::RenameCollection( + Some(2) => app.goto_screen(&Screen::SavedCollections(Some(InputOpt::RenameCollection( selected.get_id(), )))), // delete collection - Some(2) => { + Some(3) => { if let Err(e) = app.db.as_ref().delete_collection(selected.get_id()) { app.goto_screen(&Screen::SavedCollections(Some(InputOpt::RequestError( format!("Error: {e}"), @@ -153,7 +156,7 @@ pub fn handle_collection_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i )))); } // cancel - Some(3) => { + Some(4) => { app.goto_screen(&Screen::ViewSavedCollections); } _ => {} diff --git a/src/screens/input/input_screen.rs b/src/screens/input/input_screen.rs index 676c02f..e828dd4 100644 --- a/src/screens/input/input_screen.rs +++ b/src/screens/input/input_screen.rs @@ -45,31 +45,25 @@ pub fn get_input_prompt(opt: InputOpt) -> Text<'static> { pub fn handle_default_input_screen(app: &mut App, frame: &mut Frame<'_>, opt: InputOpt) { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints(vec![Constraint::Percentage(15), Constraint::Percentage(85)]) + .constraints(vec![ + Constraint::Percentage(10), + Constraint::Percentage(10), + Constraint::Percentage(80), + ]) + .horizontal_margin(6) .split(frame.size()); - let input_textbox = chunks[0]; - let text_chunk = Block::default().borders(Borders::ALL).style( - Style::default() - .bg(app.config.get_bg_color()) - .fg(Color::LightBlue) - .add_modifier(tui::style::Modifier::BOLD), - ); - frame.render_widget(text_chunk, input_textbox); - let bottom_box = centered_rect(chunks[1], crate::screens::ScreenArea::Top); + let input_textbox = chunks[1]; + let bottom_box = centered_rect(chunks[2], crate::screens::ScreenArea::Top); let prompt = get_input_prompt(opt.clone()); frame.render_widget( - Paragraph::new(prompt).style( - Style::default() - .fg(Color::LightBlue) - .add_modifier(Modifier::BOLD), - ), + Paragraph::new(prompt).style(Style::default().add_modifier(Modifier::BOLD)), centered_rect(bottom_box, crate::screens::ScreenArea::Top), ); let top_box = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) + .constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref()) .split(input_textbox); - let width = top_box[0].width.max(3) - 3; + let width = top_box[1].width.max(3) - 3; let scroll = app.input.visual_scroll(width as usize); match opt { InputOpt::URL => { @@ -161,8 +155,8 @@ pub fn handle_default_input_screen(app: &mut App, frame: &mut Frame<'_>, opt: In } let input = Paragraph::new(app.input.value()) .style(match app.input_mode { - InputMode::Normal => Style::default().fg(app.config.get_body_color()), - InputMode::Editing => Style::default().fg(Color::White), + InputMode::Normal => Style::default().fg(Color::Blue), + InputMode::Editing => Style::default().fg(Color::Yellow), }) .block(Block::default().borders(Borders::ALL).title("Input")); let (msg, style) = match app.input_mode { @@ -265,6 +259,24 @@ pub fn parse_input(message: String, opt: InputOpt, app: &mut App) { InputOpt::NewCookie => { app.goto_screen(&Screen::RequestMenu(Some(InputOpt::CookieValue(message)))); } + InputOpt::CmdDescription(id) => { + let coll_id = app + .db + .set_command_description(id, &message) + .unwrap_or_default(); + app.goto_screen(&Screen::SavedCommands { + id: coll_id, + opt: Some(InputOpt::RequestError(String::from("Description Updated"))), + }); + } + InputOpt::CollectionDescription(id) => { + app.db + .set_collection_description(id, &message) + .unwrap_or_default(); + app.goto_screen(&Screen::SavedCollections(Some(InputOpt::RequestError( + String::from("Description Updated"), + )))); + } InputOpt::CookieValue(ref name) => { let cookie = format!("{}={};", name, message); app.goto_screen(&Screen::RequestMenu(Some(InputOpt::CookieExpires(cookie)))); @@ -340,9 +352,13 @@ pub fn parse_input(message: String, opt: InputOpt, app: &mut App) { } InputOpt::ImportCollection => { if let Err(e) = app.import_postman_collection(&message) { - app.goto_screen(&Screen::Error(e.to_string())); + app.goto_screen(&Screen::SavedCollections(Some(InputOpt::AlertMessage( + e.to_string(), + )))); } else { - app.goto_screen(&Screen::Success); + app.goto_screen(&Screen::SavedCollections(Some(InputOpt::AlertMessage( + String::from("Collection Imported"), + )))); } } InputOpt::KeyLabel(id) => match app.db.set_key_label(id, &message) { @@ -354,6 +370,16 @@ pub fn parse_input(message: String, opt: InputOpt, app: &mut App) { e ))))), }, + InputOpt::CmdLabel(id) => match app.db.set_command_label(id, &message) { + Ok(collection_id) => app.goto_screen(&Screen::SavedCommands { + id: collection_id, + opt: Some(InputOpt::AlertMessage(String::from("Label Updated"))), + }), + Err(e) => app.goto_screen(&Screen::SavedCommands { + id: None, + opt: Some(InputOpt::RequestError(format!("Error: {}", e))), + }), + }, InputOpt::Auth(auth) => { parse_auth(auth, app, &message); } diff --git a/src/screens/more_flags.rs b/src/screens/more_flags.rs index 7c1ed0f..a56503a 100644 --- a/src/screens/more_flags.rs +++ b/src/screens/more_flags.rs @@ -24,16 +24,14 @@ pub fn handle_more_flags_screen(app: &mut App, frame: &mut Frame<'_>) { Some(6) => app.goto_screen(&Screen::RequestMenu(Some(InputOpt::CaPath))), // Request certificate info Some(7) => app.add_app_option(AppOptions::CertInfo), - // add progress bar - Some(8) => app.add_app_option(AppOptions::ProgressBar), // fail on error - Some(9) => app.add_app_option(AppOptions::FailOnError), + Some(8) => app.add_app_option(AppOptions::FailOnError), // wildcard match - Some(10) => app.add_app_option(AppOptions::MatchWildcard), + Some(9) => app.add_app_option(AppOptions::MatchWildcard), // user agent - Some(11) => app.goto_screen(&Screen::RequestMenu(Some(InputOpt::UserAgent))), + Some(10) => app.goto_screen(&Screen::RequestMenu(Some(InputOpt::UserAgent))), // enable tcp keepalive - Some(12) => app.add_app_option(AppOptions::TcpKeepAlive), + Some(11) => app.add_app_option(AppOptions::TcpKeepAlive), _ => {} } } diff --git a/src/screens/render.rs b/src/screens/render.rs index ecb23ea..4dbfcd5 100644 --- a/src/screens/render.rs +++ b/src/screens/render.rs @@ -175,8 +175,8 @@ pub fn handle_screen(app: &mut App, frame: &mut Frame<'_>, screen: Screen) { Screen::SavedKeys(opt) => { saved_keys::handle_saved_keys_screen(app, frame, opt); } - Screen::CmdMenu(cmd) => { - saved_commands::handle_alert_menu(app, frame, cmd); + Screen::CmdMenu { id, opt } => { + saved_commands::handle_alert_menu(app, frame, id, opt); } Screen::CookieOptions => { cookies::handle_cookies_menu(app, frame); diff --git a/src/screens/saved_commands.rs b/src/screens/saved_commands.rs index 6201008..cf4c94e 100644 --- a/src/screens/saved_commands.rs +++ b/src/screens/saved_commands.rs @@ -1,3 +1,4 @@ +use super::input::input_screen::handle_default_input_screen; use super::render::render_header_paragraph; use super::{centered_rect, error_alert_box, Screen, ScreenArea}; use crate::app::App; @@ -5,7 +6,9 @@ use crate::display::inputopt::InputOpt; use crate::display::menuopts::{CMD_MENU_OPTIONS, SAVED_COMMANDS_PARAGRAPH, SAVED_COMMANDS_TITLE}; use tui::prelude::{Constraint, Direction, Layout, Margin}; use tui::style::{Color, Modifier, Style}; -use tui::widgets::{Block, Borders, List, ListItem, ListState, Paragraph}; +use tui::text::{Line, Span}; + +use tui::widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Wrap}; use tui::Frame; pub fn handle_saved_commands_screen( @@ -20,9 +23,12 @@ pub fn handle_saved_commands_screen( .iter() .map(|x| { format!( - "Request: {} Collection: {:?}", - x.get_command(), - x.get_collection_id() + "Request: {} | Collection: {:?}", + x.label.clone().unwrap_or(String::from("No label")), + match x.collection_name.clone() { + Some(name) => name, + None => "No Collection".to_string(), + } ) }) .collect::>(), @@ -48,14 +54,23 @@ pub fn handle_saved_commands_screen( if let Some(selected) = app.selected { let cmd = commands.get(selected); if let Some(cmd) = cmd { - app.goto_screen(&Screen::CmdMenu(cmd.get_id())); + app.goto_screen(&Screen::CmdMenu { + id: cmd.get_id(), + opt: None, + }); } else { - app.goto_screen(&Screen::Error("No commands found".to_string())); + app.goto_screen(&Screen::SavedCommands { + id: None, + opt: Some(InputOpt::RequestError("No commands found".to_string())), + }); } } } -pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { +pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32, opt: Option) { + if let Some(opt) = opt { + handle_default_input_screen(app, frame, opt); + } let layout = Layout::default() .direction(Direction::Vertical) .constraints( @@ -68,15 +83,9 @@ pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { ) .horizontal_margin(5) .split(frame.size()); - // Render the alert box - let alert_box = layout[1]; - let alert_text_chunk = Block::default() - .borders(Borders::ALL) - .style(Style::default().bg(Color::Black).fg(Color::LightGreen)) - .title("Alert"); let options_box = layout[1].inner(&Margin { vertical: 1, - horizontal: 1, + horizontal: 25, }); let mut list_state = ListState::with_selected(ListState::default(), Some(app.cursor)); app.state = Some(list_state.clone()); @@ -88,7 +97,7 @@ pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { .block(Block::default()) .highlight_style( Style::default() - .bg(Color::White) + .bg(Color::Blue) .fg(Color::Black) .add_modifier(Modifier::BOLD), ) @@ -96,22 +105,81 @@ pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { let cmd_str = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) - .split(alert_box)[1]; + .split(layout[1])[1]; if let Ok(command) = app.db.as_ref().get_command_by_id(cmd) { - let paragraph = Paragraph::new(format!("{:?}", command)) - .block(Block::default().borders(Borders::ALL).title("Command")) - .alignment(tui::layout::Alignment::Center); - frame.render_widget(paragraph, cmd_str); - frame.render_widget(alert_text_chunk, alert_box); + let collection_name = match app + .db + .as_ref() + .get_collection_by_id(command.collection_id.unwrap_or(0)) + { + Ok(collection) => collection.name, + Err(_) => "No Collection".to_string(), + }; + let alert_text = vec![ + Line::raw("\n"), + Line::default().spans(vec![ + Span::styled("Label: ", Style::default().fg(Color::LightGreen)), + Span::styled( + command.label.clone().unwrap_or("None".to_string()), + Style::default().fg(Color::White), + ), + ]), + Line::default().spans(vec![ + Span::styled("Description: ", Style::default().fg(Color::LightGreen)), + Span::styled( + command.description.clone().unwrap_or("None".to_string()), + Style::default().fg(Color::White), + ), + ]), + Line::default().spans(vec![ + Span::styled("Collection: ", Style::default().fg(Color::LightGreen)), + Span::styled(collection_name, Style::default().fg(Color::White)), + ]), + Line::default().spans(vec![ + Span::styled("ID: ", Style::default().fg(Color::LightGreen)), + Span::styled(command.id.to_string(), Style::default().fg(Color::White)), + ]), + ]; + let alert_text = List::new(alert_text) + .block( + Block::default() + .borders(Borders::ALL) + .title("Command Details"), + ) + .style(Style::default().fg(Color::Blue)) + .highlight_style(Style::default().fg(Color::LightGreen)); frame.render_stateful_widget(list, options_box, &mut list_state); + frame.render_widget(alert_text, layout[0]); + let header = Block::default().borders(Borders::ALL).title("* Request *"); + frame.render_widget(header, layout[0]); + let paragraph = Paragraph::new(command.get_command()) + .block(Block::default().borders(Borders::ALL).title("* Command *")) + .alignment(tui::layout::Alignment::Center) + .centered() + .wrap(Wrap::default()); + frame.render_widget(paragraph, cmd_str); match app.selected { // execute saved command Some(0) => { app.execute_saved_command(command.get_curl_json()); app.goto_screen(&Screen::Response(app.response.clone().unwrap())); } - // delete item + // add a label Some(1) => { + app.goto_screen(&Screen::CmdMenu { + id: cmd, + opt: Some(InputOpt::CmdLabel(cmd)), + }); + } + // add a description + Some(2) => { + app.goto_screen(&Screen::CmdMenu { + id: cmd, + opt: Some(InputOpt::CmdDescription(cmd)), + }); + } + // delete item + Some(3) => { if let Err(e) = app.delete_item(command.get_id()) { app.goto_screen(&Screen::SavedCommands { id: None, @@ -127,7 +195,7 @@ pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { } } // copy to clipboard - Some(2) => { + Some(4) => { if let Err(e) = app.copy_to_clipboard(command.get_command()) { app.goto_screen(&Screen::Error(e.to_string())); } @@ -139,7 +207,7 @@ pub fn handle_alert_menu(app: &mut App, frame: &mut Frame<'_>, cmd: i32) { }); } // cancel - Some(3) => { + Some(5) => { app.goto_screen(&Screen::SavedCommands { id: None, opt: None, diff --git a/src/screens/screen.rs b/src/screens/screen.rs index 7aef4d7..2665487 100644 --- a/src/screens/screen.rs +++ b/src/screens/screen.rs @@ -33,7 +33,10 @@ pub enum Screen { ViewBody, MoreFlags, Headers, - CmdMenu(i32), + CmdMenu { + id: i32, + opt: Option, + }, KeysMenu(usize), RequestBodyInput, CookieOptions, @@ -47,6 +50,7 @@ impl Screen { Screen::SavedKeys(opt) => opt.is_some(), Screen::RequestBodyInput => true, Screen::SavedCollections(opt) => opt.is_some(), + Screen::CmdMenu { opt, .. } => opt.is_some(), _ => false, } } @@ -69,7 +73,7 @@ impl Display for Screen { Screen::ViewBody => "ViewBody", Screen::MoreFlags => "MoreFlags", Screen::Headers => "Headers", - Screen::CmdMenu(_) => "CmdMenu", + Screen::CmdMenu { .. } => "CmdMenu", Screen::KeysMenu(_) => "KeysMenu", Screen::RequestBodyInput => "RequestBodyInput", Screen::SavedCollections(_) => "Saved Collections", @@ -165,7 +169,7 @@ impl<'a> Screen { Screen::RequestBodyInput => { vec![ListItem::new("Request Body Input").style(Style::default().fg(Color::Green))] } - Screen::CmdMenu(_) => CMD_MENU_OPTIONS + Screen::CmdMenu { .. } => CMD_MENU_OPTIONS .iter() .map(|i| ListItem::new(format!("{i}{}", NEWLINE))) .collect(), diff --git a/test_collection.json b/test_collection.json new file mode 100644 index 0000000..f1c3c6b --- /dev/null +++ b/test_collection.json @@ -0,0 +1,40 @@ +{ + "info": { + "name": "Test Collection", + "version": "v2.1.0", + "description": "This is a demo collection.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/" + }, + "item": [ + { + "id": "my-first-item", + "name": "My First Item", + "description": "This is an Item that contains a single HTTP GET request. It doesn't really do much yet!", + "request": { + "description": "This is a sample POST request", + "url": "https://echo.getpostman.com/post", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Host", + "value": "echo.getpostman.com" + } + ], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "my-body-variable", + "value": "Something Awesome!" + } + ] + } + }, + "response": [] + } + ] +}