Skip to content

Commit

Permalink
feat: redesign of create request form
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed Jun 11, 2024
1 parent e71b5a8 commit d2aa4bd
Show file tree
Hide file tree
Showing 9 changed files with 427 additions and 129 deletions.
126 changes: 37 additions & 89 deletions hac-client/src/pages/collection_viewer/collection_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use hac_core::command::Command;
use hac_core::net::request_manager::Response;

use crate::pages::collection_viewer::collection_store::{CollectionStore, CollectionStoreAction};
use crate::pages::collection_viewer::request_editor::RequestEditor;
use crate::pages::collection_viewer::request_uri::RequestUri;
use crate::pages::collection_viewer::response_viewer::ResponseViewer;
use crate::pages::collection_viewer::sidebar::Sidebar;
use crate::pages::collection_viewer::request_editor::{RequestEditor, RequestEditorEvent};
use crate::pages::collection_viewer::request_uri::{RequestUri, RequestUriEvent};
use crate::pages::collection_viewer::response_viewer::{ResponseViewer, ResponseViewerEvent};
use crate::pages::collection_viewer::sidebar::{self, Sidebar, SidebarEvent};
use crate::pages::input::Input;
use crate::pages::overlay::draw_overlay;
use crate::pages::{Eventful, Renderable};
Expand All @@ -24,11 +24,6 @@ use ratatui::widgets::{Block, Borders, Clear, Padding, Paragraph};
use ratatui::Frame;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};

use super::request_editor::RequestEditorEvent;
use super::request_uri::RequestUriEvent;
use super::response_viewer::ResponseViewerEvent;
use super::sidebar::{self, SidebarEvent};

#[derive(Debug, PartialEq)]
pub struct ExplorerLayout {
pub hint_pane: Rect,
Expand All @@ -43,6 +38,7 @@ pub struct ExplorerLayout {
pub enum CollectionViewerOverlay {
None,
CreateRequest,
CreateDirectory,
RequestMethod,
HeadersHelp,
HeadersDelete,
Expand Down Expand Up @@ -168,33 +164,33 @@ impl<'cv> CollectionViewer<'cv> {
let layout = build_layout(size);
let (request_tx, response_rx) = unbounded_channel::<Response>();

CollectionViewer {
request_editor: RequestEditor::new(
colors,
config,
collection_store.clone(),
layout.req_editor,
),
response_viewer: ResponseViewer::new(
colors,
collection_store.clone(),
None,
layout.response_preview,
),
sidebar: sidebar::Sidebar::new(colors, collection_store.clone()),
request_uri: RequestUri::new(colors, collection_store.clone(), layout.req_uri),
let sidebar = sidebar::Sidebar::new(colors, collection_store.clone());

let request_editor =
RequestEditor::new(colors, config, collection_store.clone(), layout.req_editor);

let response_viewer = ResponseViewer::new(
colors,
collection_store.clone(),
None,
layout.response_preview,
);

let request_uri = RequestUri::new(colors, collection_store.clone(), layout.req_uri);

CollectionViewer {
request_editor,
response_viewer,
sidebar,
request_uri,
colors,
layout,
global_command_sender: None,
collection_sync_timer: std::time::Instant::now(),

create_req_form_state: CreateReqFormState::default(),

responses_map: HashMap::default(),
response_rx,
request_tx,

dry_run,
collection_store,
}
Expand Down Expand Up @@ -223,62 +219,6 @@ impl<'cv> CollectionViewer<'cv> {
}
}

fn draw_req_uri_hint(&self, frame: &mut Frame) {
let hint = "[type anything -> edit] [enter -> execute request] [<C-c> -> quit] [tab -> switch pane]"
.fg(self.colors.normal.magenta)
.into_centered_line();

frame.render_widget(hint, self.layout.hint_pane);
}

fn draw_sidebar_hint(&self, frame: &mut Frame) {
let hint =
"[j/k -> navigate] [enter -> select item] [n -> create request] [? -> help] [<C-c> -> quit] [tab -> switch pane]"
.fg(self.colors.normal.magenta)
.into_centered_line();

frame.render_widget(hint, self.layout.hint_pane);
}

fn draw_preview_hint(&self, frame: &mut Frame) {
let hint = match self
.collection_store.borrow()
.get_selected_pane()
.as_ref()
.is_some_and(|selected| selected.eq(&PaneFocus::Preview))
{
false => "[j/k -> scroll] [enter -> interact] [? -> help] [<C-c> -> quit] [tab -> switch pane]"
.fg(self.colors.normal.magenta)
.into_centered_line(),
true => {
"[j/k -> scroll] [esc -> deselect] [tab -> switch tab] [? -> help] [<C-c> -> quit] [tab -> switch tab]"
.fg(self.colors.normal.magenta)
.into_centered_line()
}
};

frame.render_widget(hint, self.layout.hint_pane);
}

fn draw_editor_hint(&self, frame: &mut Frame) {
let hint = match self
.collection_store
.borrow()
.get_selected_pane()
.as_ref()
.is_some_and(|selected| selected.eq(&PaneFocus::Editor))
{
false => "[enter -> interact] [? -> help] [<C-c> -> quit] [tab -> switch pane]"
.fg(self.colors.normal.magenta)
.into_centered_line(),
true => "[esc -> deselect] [tab -> switch tab] [? -> help] [<C-c> -> quit] [tab -> switch tab]"
.fg(self.colors.normal.magenta)
.into_centered_line(),
};

frame.render_widget(hint, self.layout.hint_pane);
}

fn draw_create_request_form(&mut self, frame: &mut Frame) {
let size = self.layout.create_req_form;
let item_height = 3;
Expand Down Expand Up @@ -675,7 +615,12 @@ impl Renderable for CollectionViewer<'_> {

let overlay = self.collection_store.borrow().peek_overlay();
match overlay {
CollectionViewerOverlay::CreateRequest => self.draw_create_request_form(frame),
CollectionViewerOverlay::CreateRequest => {
self.sidebar.draw_overlay(frame, overlay)?;
}
CollectionViewerOverlay::CreateDirectory => {
self.sidebar.draw_overlay(frame, overlay)?;
}
CollectionViewerOverlay::RequestMethod => self.draw_request_method_form(frame),
CollectionViewerOverlay::HeadersHelp => {
self.request_editor.draw_overlay(frame, overlay)?
Expand Down Expand Up @@ -803,11 +748,14 @@ impl Eventful for CollectionViewer<'_> {
if let Some(curr_pane) = selected_pane {
match curr_pane {
PaneFocus::Sidebar => match self.sidebar.handle_key_event(key_event)? {
Some(SidebarEvent::CreateRequest) => {
self.collection_store
.borrow_mut()
.push_overlay(CollectionViewerOverlay::CreateRequest);
}
Some(SidebarEvent::CreateRequest) => self
.collection_store
.borrow_mut()
.push_overlay(CollectionViewerOverlay::CreateRequest),
Some(SidebarEvent::CreateDirectory) => self
.collection_store
.borrow_mut()
.push_overlay(CollectionViewerOverlay::CreateDirectory),
Some(SidebarEvent::RemoveSelection) => self.update_selection(None),
Some(SidebarEvent::Quit) => return Ok(Some(Command::Quit)),
// when theres no event we do nothing
Expand Down
3 changes: 1 addition & 2 deletions hac-client/src/pages/collection_viewer/request_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use hac_core::text_object::{TextObject, Write};
use headers_editor::{HeadersEditor, HeadersEditorEvent};

use crate::pages::collection_viewer::collection_store::CollectionStore;
use crate::pages::collection_viewer::collection_viewer::{CollectionViewerOverlay, PaneFocus};
use crate::pages::under_construction::UnderConstruction;
use crate::pages::Eventful;
use crate::pages::Renderable;
Expand All @@ -28,8 +29,6 @@ use ratatui::style::{Style, Stylize};
use ratatui::widgets::{Block, Borders, Tabs};
use ratatui::Frame;

use super::collection_viewer::{CollectionViewerOverlay, PaneFocus};

/// set of possible events the edtior can send to the parent
#[derive(Debug)]
pub enum RequestEditorEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::pages::overlay::make_overlay;
use crate::pages::{Eventful, Renderable};

use std::cell::RefCell;
use std::ops::{Add, Div};
use std::ops::{Add, Div, Sub};
use std::rc::Rc;

use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
Expand Down Expand Up @@ -135,7 +135,7 @@ impl Renderable for HeadersEditorForm<'_> {

let total_size = logo_size.add(11).add(2);
let mut size = Rect::new(
size.width.div(2).saturating_sub(25),
size.width.div(2).sub(25),
size.height
.div(2)
.saturating_sub(logo_size.div(2))
Expand All @@ -151,13 +151,18 @@ impl Renderable for HeadersEditorForm<'_> {
size.y = size.height.div(2).saturating_sub(5);
}

let name_input = Input::new(self.colors, "Name".into());
let value_input = Input::new(self.colors, "Value".into());
let mut name_input = Input::new(self.colors, "Name".into());
let mut value_input = Input::new(self.colors, "Value".into());
let hint = Paragraph::new(
"Press enter to confirm, press esc to cancel".fg(self.colors.bright.black),
)
.centered();

match self.focused_input {
HeadersEditorFormInput::Name => name_input.focus(),
HeadersEditorFormInput::Value => value_input.focus(),
}

if !logo.is_empty() {
let logo = logo
.iter()
Expand Down
75 changes: 55 additions & 20 deletions hac-client/src/pages/collection_viewer/sidebar.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
mod create_request_form;

use hac_core::collection::types::{Request, RequestKind, RequestMethod};

use crate::pages::collection_viewer::collection_store::{CollectionStore, CollectionStoreAction};
use crate::pages::collection_viewer::collection_viewer::{CollectionViewerOverlay, PaneFocus};
use crate::pages::collection_viewer::sidebar::create_request_form::CreateRequestForm;
use crate::pages::collection_viewer::sidebar::create_request_form::CreateRequestFormEvent;
use crate::pages::{Eventful, Renderable};

use std::cell::RefCell;
Expand All @@ -15,14 +20,15 @@ use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Paragraph};
use ratatui::Frame;

use super::collection_viewer::PaneFocus;

/// set of events Sidebar can emit to the caller when handling events.
#[derive(Debug)]
pub enum SidebarEvent {
/// user pressed CreateRequest hotkey, which should notify the caller to open
/// user pressed `CreateRequest (n)` hotkey, which should notify the caller to open
/// the create_request_form and properly handle the creation of a new request
CreateRequest,
/// user pressed `CreateDirectory (d)` hotkey, which should notify the caller to open
/// the `create_directory_form` overlay to create a new directory on the collection
CreateDirectory,
/// user pressed `Esc` so we notify the caller to remove the selection from
/// this pane, essentially bubbling the key handling scope to the caller
RemoveSelection,
Expand All @@ -36,6 +42,7 @@ pub struct Sidebar<'sbar> {
colors: &'sbar hac_colors::Colors,
lines: Vec<Paragraph<'static>>,
collection_store: Rc<RefCell<CollectionStore>>,
create_request_form: CreateRequestForm<'sbar>,
}

impl<'sbar> Sidebar<'sbar> {
Expand All @@ -45,6 +52,7 @@ impl<'sbar> Sidebar<'sbar> {
) -> Self {
let mut sidebar = Self {
colors,
create_request_form: CreateRequestForm::new(colors, collection_store.clone()),
lines: vec![],
collection_store,
};
Expand All @@ -65,6 +73,22 @@ impl<'sbar> Sidebar<'sbar> {
self.colors,
);
}

pub fn draw_overlay(
&mut self,
frame: &mut Frame,
overlay: CollectionViewerOverlay,
) -> anyhow::Result<()> {
match overlay {
CollectionViewerOverlay::CreateRequest => {
self.create_request_form.draw(frame, frame.size())?;
}
CollectionViewerOverlay::CreateDirectory => {}
_ => {}
};

Ok(())
}
}

impl<'sbar> Renderable for Sidebar<'sbar> {
Expand Down Expand Up @@ -123,33 +147,44 @@ impl<'a> Eventful for Sidebar<'a> {
"handled an event to the sidebar while it was not selected"
);

let mut store = self.collection_store.borrow_mut();

match store.peek_overlay() {
CollectionViewerOverlay::CreateRequest => {
match self.create_request_form.handle_key_event(key_event)? {
Some(CreateRequestFormEvent::Confirm) => return Ok(None),
Some(CreateRequestFormEvent::Cancel) => _ = store.pop_overlay(),
None => return Ok(None),
}
}
CollectionViewerOverlay::CreateDirectory => todo!(),
_ => {}
};

if let (KeyCode::Char('c'), KeyModifiers::CONTROL) = (key_event.code, key_event.modifiers) {
return Ok(Some(SidebarEvent::Quit));
}

let mut store = self.collection_store.borrow_mut();
match key_event.code {
KeyCode::Enter => {
if store.get_hovered_request().is_some() && store.get_requests().is_some() {
let request = store.find_hovered_request();
match request {
RequestKind::Nested(_) => {
store
.dispatch(CollectionStoreAction::ToggleDirectory(request.get_id()));
}
RequestKind::Single(req) => {
store.dispatch(CollectionStoreAction::SetSelectedRequest(Some(req)));
}
if store.get_requests().is_none() || store.get_hovered_request().is_none() {
return Ok(None);
}

let request = store.find_hovered_request();
match request {
RequestKind::Nested(_) => {
store.dispatch(CollectionStoreAction::ToggleDirectory(request.get_id()));
}
RequestKind::Single(req) => {
store.dispatch(CollectionStoreAction::SetSelectedRequest(Some(req)));
}
}
}
KeyCode::Char('j') | KeyCode::Down => {
store.dispatch(CollectionStoreAction::HoverNext);
}
KeyCode::Char('k') | KeyCode::Up => {
store.dispatch(CollectionStoreAction::HoverPrev);
}
KeyCode::Char('j') | KeyCode::Down => store.dispatch(CollectionStoreAction::HoverNext),
KeyCode::Char('k') | KeyCode::Up => store.dispatch(CollectionStoreAction::HoverPrev),
KeyCode::Char('n') => return Ok(Some(SidebarEvent::CreateRequest)),
KeyCode::Char('d') => return Ok(Some(SidebarEvent::CreateDirectory)),
KeyCode::Esc => return Ok(Some(SidebarEvent::RemoveSelection)),
_ => {}
}
Expand Down
Loading

0 comments on commit d2aa4bd

Please sign in to comment.