Skip to content

Commit

Permalink
feat: editing requests from sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed Oct 6, 2024
1 parent 81582e7 commit c38b66a
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl CreateRequestForm {
KeyCode::Enter => {
let request = hac_store::collection::Request::new(self.name.clone(), self.method, self.parent);
hac_store::collection::push_request(request, self.parent);
hac_store::collection::rebuild_tree_layout();
router_drop_dialog!(&self.messager, Routes::CreateRequest.into());
}
_ => {}
Expand All @@ -88,6 +89,7 @@ impl CreateRequestForm {
match key_event.code {
KeyCode::Char('j') | KeyCode::Down => self.parent_listing.select_down(),
KeyCode::Char('k') | KeyCode::Up => self.parent_listing.select_up(),
KeyCode::Esc => self.form_step = FormStep::MainForm,
KeyCode::Enter => {
if hac_store::collection::has_folders() {
self.parent = Some(self.parent_listing.selected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::mpsc::{channel, Sender};

use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use hac_core::command::Command;
use hac_store::collection::ReqMethod;
use hac_store::collection::{EntryStatus, ReqMethod, WhichSlab};
use hac_store::slab::Key;
use ratatui::layout::Rect;
use ratatui::Frame;
Expand Down Expand Up @@ -75,12 +75,74 @@ impl EditRequestForm {
KeyCode::Tab => self.focus.next(),
KeyCode::BackTab => self.focus.prev(),
KeyCode::Esc => {
router_drop_dialog!(&self.messager, Routes::CreateRequest.into());
router_drop_dialog!(&self.messager, Routes::EditRequest.into());
}
KeyCode::Enter => {
let request = hac_store::collection::Request::new(self.name.clone(), self.method, self.parent);
hac_store::collection::push_request(request, self.parent);
router_drop_dialog!(&self.messager, Routes::CreateRequest.into());
// editing a request gives us a few possible scenarios:
// 1. parent of the request didn't change, either if it had no parent and still has
// no parent, or if it had one and it wasn't changed.
// - in this case, we just need to update the request on the current slab it
// lives in
// 2. parent of the request changed from not having a parent to having a parent.
// - in this case we need to remove the request from root_requests and move it
// to requests, also updating the new parent to hold the key to its new request
// 3. parent of the request changed from having a parent to not having a parent.
// - similar to the previous one, we need to remove it from requests, and also
// remove the key from the current parent, and then add it into root_requests.
// 4. parent of the request changed to another parent, so we only need to update
// both folders
match (self.prev_parent, self.parent) {
(Some(a), Some(b)) if a == b => hac_store::collection::get_request_mut(self.key, |req, _| {
req.name.clone_from(&self.name);
req.method = self.method;
req.parent = self.parent;
}),
(None, None) => hac_store::collection::get_root_request_mut(self.key, |req, _| {
req.name.clone_from(&self.name);
req.method = self.method;
req.parent = self.parent;
}),
(None, Some(new_parent)) => {
let status = hac_store::collection::get_root_request(self.key, |_, status| status);
let is_selected = matches!(status, EntryStatus::Selected | EntryStatus::Both);
let mut req = hac_store::collection::remove_root_request(self.key);
req.name.clone_from(&self.name);
req.method = self.method;
req.parent = self.parent;
let key = hac_store::collection::push_request(req, Some(new_parent));
hac_store::collection::set_hovered_request(Some((WhichSlab::Requests, key)));
if is_selected {
hac_store::collection::set_selected_request(Some((WhichSlab::Requests, key)));
}
}
(Some(_), None) => {
let status = hac_store::collection::get_request(self.key, |_, status| status);
let is_selected = matches!(status, EntryStatus::Selected | EntryStatus::Both);
let mut req = hac_store::collection::remove_request(self.key);
req.name.clone_from(&self.name);
req.method = self.method;
req.parent = self.parent;
let key = hac_store::collection::push_request(req, None);
hac_store::collection::set_hovered_request(Some((WhichSlab::RootRequests, key)));
if is_selected {
hac_store::collection::set_selected_request(Some((WhichSlab::RootRequests, key)));
}
}
(Some(curr_parent), Some(new_parent)) => {
hac_store::collection::get_request_mut(self.key, |req, _| {
req.name.clone_from(&self.name);
req.method = self.method;
req.parent = self.parent;
});
hac_store::collection::get_folder_mut(curr_parent, |folder, _| {
folder.requests.retain(|r| *r != self.key)
});
hac_store::collection::get_folder_mut(new_parent, |folder, _| folder.requests.push(self.key));
}
}

hac_store::collection::rebuild_tree_layout();
router_drop_dialog!(&self.messager, Routes::EditRequest.into());
}
_ => {}
};
Expand All @@ -92,6 +154,7 @@ impl EditRequestForm {
match key_event.code {
KeyCode::Char('j') | KeyCode::Down => self.parent_listing.select_down(),
KeyCode::Char('k') | KeyCode::Up => self.parent_listing.select_up(),
KeyCode::Esc => self.form_step = FormStep::MainForm,
KeyCode::Enter => {
if hac_store::collection::has_folders() {
self.parent = Some(self.parent_listing.selected);
Expand All @@ -110,8 +173,6 @@ impl Renderable for EditRequestForm {
type Input = ();
type Output = ();

fn data(&self, _requester: u8) -> Self::Output {}

fn draw(&mut self, frame: &mut Frame, _: Rect) -> anyhow::Result<()> {
make_overlay(self.colors.clone(), self.colors.normal.black, 0.15, frame);

Expand All @@ -132,6 +193,12 @@ impl Renderable for EditRequestForm {

Ok(())
}

fn data(&self, _requester: u8) -> Self::Output {}

fn attach_navigator(&mut self, messager: Sender<RouterMessage>) {
self.messager = messager;
}
}

impl Eventful for EditRequestForm {
Expand Down
18 changes: 9 additions & 9 deletions hac-client/src/pages/collection_viewer/sidebar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,27 @@ impl Sidebar {
if self.show_extended_hint {
let lines = vec![
Line::from(vec![
"j/k ↑/↓".fg(self.colors.normal.green),
"j/k ↑/↓".fg(self.colors.bright.green).bold(),
" - Choose • ".fg(self.colors.bright.black),
"n".fg(self.colors.normal.green),
"n".fg(self.colors.bright.green).bold(),
" - New request • ".fg(self.colors.bright.black),
"Enter".fg(self.colors.normal.green),
"Enter".fg(self.colors.bright.green).bold(),
" - Select request".fg(self.colors.bright.black),
]),
Line::from(vec![
"?".fg(self.colors.normal.green),
"?".fg(self.colors.bright.green).bold(),
" - Show less • ".fg(self.colors.bright.black),
"Ctrl c".fg(self.colors.normal.green),
"Ctrl c".fg(self.colors.bright.green).bold(),
" - Quit • ".fg(self.colors.bright.black),
"d".fg(self.colors.normal.green),
"d".fg(self.colors.bright.green).bold(),
" - Delete item".fg(self.colors.bright.black),
]),
Line::from(vec![
"e".fg(self.colors.normal.green),
"e".fg(self.colors.bright.green).bold(),
" - Edit • ".fg(self.colors.bright.black),
"Tab".fg(self.colors.normal.green),
"Tab".fg(self.colors.bright.green).bold(),
" - Next • ".fg(self.colors.bright.black),
"S-Tab".fg(self.colors.normal.green),
"S-Tab".fg(self.colors.bright.green).bold(),
" - Prev".fg(self.colors.bright.black),
]),
];
Expand Down
112 changes: 101 additions & 11 deletions hac-store/src/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct ReqTree {
pub nodes: Vec<ReqTreeNode>,
}

#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EntryStatus {
None,
Hovered,
Expand Down Expand Up @@ -244,14 +244,52 @@ pub fn tree_layout() -> ReqTree {
nodes
}

pub fn get_root_request<F>(key: Key, f: F)
pub fn remove_request(key: Key) -> Request {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
let req = collection.requests.remove(key);
assert!(req.parent.is_some());
let folder = collection.folders.get_mut(req.parent.unwrap());
folder.requests.retain(|r| *r != key);
req
})
}

pub fn remove_root_request(key: Key) -> Request {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
collection.root_requests.remove(key)
})
}

pub fn get_root_request<F, R>(key: Key, f: F) -> R
where
F: FnOnce(&Request, EntryStatus),
F: FnOnce(&Request, EntryStatus) -> R,
{
HAC_STORE.with_borrow(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_ref().unwrap();
let req = collection.root_requests.get(key);
let is_hovered = collection
.hovered_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::RootRequests) && key == k);
let is_selected = collection
.selected_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::RootRequests) && key == k);
f(req, (is_hovered, is_selected).into())
})
}

pub fn get_root_request_mut<F>(key: Key, f: F)
where
F: FnOnce(&mut Request, EntryStatus),
{
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
let req = collection.root_requests.get_mut(key);
let is_hovered = collection
.hovered_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::RootRequests) && key == k);
Expand All @@ -262,14 +300,32 @@ where
})
}

pub fn get_request<F>(key: Key, f: F)
pub fn get_request<F, R>(key: Key, f: F) -> R
where
F: FnOnce(&Request, EntryStatus),
F: FnOnce(&Request, EntryStatus) -> R,
{
HAC_STORE.with_borrow(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_ref().unwrap();
let req = collection.requests.get(key);
let is_hovered = collection
.hovered_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::Requests) && key == k);
let is_selected = collection
.selected_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::Requests) && key == k);
f(req, (is_hovered, is_selected).into())
})
}

pub fn get_request_mut<F>(key: Key, f: F)
where
F: FnOnce(&mut Request, EntryStatus),
{
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
let req = collection.requests.get_mut(key);
let is_hovered = collection
.hovered_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::Requests) && key == k);
Expand Down Expand Up @@ -317,6 +373,24 @@ where
})
}

pub fn get_folder_mut<F>(key: Key, f: F)
where
F: FnOnce(&mut Folder, EntryStatus),
{
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
let folder = collection.folders.get_mut(key);
let is_hovered = collection
.hovered_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::Folders) && key == k);
let is_selected = collection
.selected_request
.is_some_and(|(slab, k)| matches!(slab, WhichSlab::Folders) && key == k);
f(folder, (is_hovered, is_selected).into());
})
}

pub fn hover_next() {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
Expand Down Expand Up @@ -448,6 +522,22 @@ pub fn hover_prev() {
})
}

pub fn set_selected_request(new_hovered: Option<(WhichSlab, Key)>) {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
collection.selected_request = new_hovered;
})
}

pub fn set_hovered_request(new_hovered: Option<(WhichSlab, Key)>) {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
collection.hovered_request = new_hovered;
})
}

pub fn get_hovered_request<F, R>(f: F) -> R
where
F: FnOnce(Option<(WhichSlab, Key)>) -> R,
Expand Down Expand Up @@ -476,7 +566,7 @@ pub fn toggle_dir(key: Key) {
});
}

pub fn push_request(request: Request, parent: Option<Key>) {
pub fn push_request(request: Request, parent: Option<Key>) -> Key {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
Expand All @@ -485,14 +575,14 @@ pub fn push_request(request: Request, parent: Option<Key>) {
let new_key = collection.requests.push(request);
let folder = collection.folders.get_mut(key);
folder.requests.push(new_key);
new_key
}
None => _ = collection.root_requests.push(request),
};
});
rebuild_tree_layout();
None => collection.root_requests.push(request),
}
})
}

fn rebuild_tree_layout() {
pub fn rebuild_tree_layout() {
HAC_STORE.with_borrow_mut(|store| {
assert!(store.collection.is_some());
let collection = store.collection.as_mut().unwrap();
Expand Down
10 changes: 8 additions & 2 deletions hac-store/src/slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,17 @@ impl<T> Slab<T> {
}

pub fn len(&self) -> usize {
self.inner.len()
self.inner
.iter()
.filter_map(|e| match e {
Entry::Full(val) => Some(val),
Entry::Free(_) => None,
})
.count()
}

pub fn is_empty(&self) -> bool {
self.inner.is_empty()
self.len() == 0
}

pub fn next_idx(&self) -> Key {
Expand Down

0 comments on commit c38b66a

Please sign in to comment.