event.rs and ui.rs refactor for the forms page(moved logic to the forms page dir and just calling it now)

This commit is contained in:
filipriec
2025-08-30 16:42:04 +02:00
parent a0757efe8b
commit 46149c09db
6 changed files with 143 additions and 79 deletions

View File

@@ -82,8 +82,6 @@ impl TableDependencyGraph {
} }
} }
// ... (NavigationState struct and its new(), activate_*, deactivate(), add_char(), remove_char(), move_*, autocomplete_selected(), get_display_input() methods are unchanged) ...
pub struct NavigationState { pub struct NavigationState {
pub active: bool, pub active: bool,
pub input: String, pub input: String,

View File

@@ -36,6 +36,7 @@ use crate::pages::register::RegisterResult;
use crate::pages::routing::{Router, Page}; use crate::pages::routing::{Router, Page};
use crate::movement::MovementAction; use crate::movement::MovementAction;
use crate::dialog; use crate::dialog;
use crate::pages::forms;
use crate::pages::forms::FormState; use crate::pages::forms::FormState;
use crate::pages::forms::logic::{save, revert, SaveOutcome}; use crate::pages::forms::logic::{save, revert, SaveOutcome};
use crate::search::state::SearchState; use crate::search::state::SearchState;
@@ -384,6 +385,14 @@ impl EventHandler {
} }
} }
} }
} else if let Page::Form(path) = &router.current {
// NEW: Delegate Form event handling
return forms::event::handle_form_event(
event,
app_state,
path,
&mut self.ideal_cursor_column
);
} }
} }
if toggle_sidebar( if toggle_sidebar(
@@ -858,25 +867,14 @@ impl EventHandler {
&mut self.auth_client, &mut self.auth_client,
app_state, app_state,
) )
.await?; .await?;
Ok(EventOutcome::Ok(message)) Ok(EventOutcome::Ok(message))
} else { } else {
let save_outcome = if let Page::Form(path) = &router.current { if let Page::Form(path) = &router.current {
save( forms::event::save_form(app_state, path, &mut self.grpc_client).await
app_state,
path,
&mut self.grpc_client,
)
.await?
} else { } else {
SaveOutcome::NoChange Ok(EventOutcome::Ok("Nothing to save".to_string()))
}; }
let message = match save_outcome {
SaveOutcome::NoChange => "No changes to save.".to_string(),
SaveOutcome::UpdatedExisting => "Entry updated.".to_string(),
SaveOutcome::CreatedNew(_) => "New entry created.".to_string(),
};
Ok(EventOutcome::DataSaved(save_outcome, message))
} }
} }
"force_quit" => { "force_quit" => {
@@ -898,19 +896,18 @@ impl EventHandler {
&mut self.auth_client, &mut self.auth_client,
app_state, app_state,
) )
.await? .await?
} else { } else if let Page::Form(path) = &router.current {
let save_outcome = if let Page::Form(path) = &router.current { let save_result = forms::event::save_form(app_state, path, &mut self.grpc_client).await?;
save(app_state, path, &mut self.grpc_client).await? match save_result {
} else { EventOutcome::DataSaved(_, msg) => msg,
SaveOutcome::NoChange EventOutcome::Ok(msg) => msg,
}; _ => "Saved".to_string(),
match save_outcome {
SaveOutcome::NoChange => "No changes to save.".to_string(),
SaveOutcome::UpdatedExisting => "Entry updated.".to_string(),
SaveOutcome::CreatedNew(_) => "New entry created.".to_string(),
} }
} else {
"No changes to save.".to_string()
}; };
if let Page::Form(path) = &router.current { if let Page::Form(path) = &router.current {
if let Some(editor) = app_state.editor_for_path(path) { if let Some(editor) = app_state.editor_for_path(path) {
editor.cleanup_cursor()?; editor.cleanup_cursor()?;
@@ -918,8 +915,8 @@ impl EventHandler {
} }
terminal.cleanup()?; terminal.cleanup()?;
Ok(EventOutcome::Exit(format!( Ok(EventOutcome::Exit(format!(
"{}. Exiting application.", "{}. Exiting application.",
message message
))) )))
} }
"revert" => { "revert" => {
@@ -933,7 +930,7 @@ impl EventHandler {
.await .await
} else { } else {
if let Page::Form(path) = &router.current { if let Page::Form(path) = &router.current {
revert(app_state, path, &mut self.grpc_client).await? return forms::event::revert_form(app_state, path, &mut self.grpc_client).await;
} else { } else {
"Nothing to revert".to_string() "Nothing to revert".to_string()
} }

View File

@@ -0,0 +1,62 @@
// src/pages/forms/event.rs
use anyhow::Result;
use crossterm::event::Event;
use canvas::keymap::KeyEventOutcome;
use crate::{
state::app::state::AppState,
pages::forms::{FormState, logic},
modes::handlers::event::EventOutcome,
};
pub fn handle_form_event(
event: Event,
app_state: &mut AppState,
path: &str,
ideal_cursor_column: &mut usize,
) -> Result<EventOutcome> {
if let Event::Key(key_event) = event {
if let Some(editor) = app_state.editor_for_path(path) {
match editor.handle_key_event(key_event) {
KeyEventOutcome::Consumed(Some(msg)) => {
return Ok(EventOutcome::Ok(msg));
}
KeyEventOutcome::Consumed(None) => {
return Ok(EventOutcome::Ok("Form input updated".into()));
}
KeyEventOutcome::Pending => {
return Ok(EventOutcome::Ok("Waiting for next key...".into()));
}
KeyEventOutcome::NotMatched => {
// fall through to navigation / save / revert
}
}
}
}
Ok(EventOutcome::Ok(String::new()))
}
// Save wrapper
pub async fn save_form(
app_state: &mut AppState,
path: &str,
grpc_client: &mut crate::services::grpc_client::GrpcClient,
) -> Result<EventOutcome> {
let outcome = logic::save(app_state, path, grpc_client).await?;
let message = match outcome {
logic::SaveOutcome::NoChange => "No changes to save.".to_string(),
logic::SaveOutcome::UpdatedExisting => "Entry updated.".to_string(),
logic::SaveOutcome::CreatedNew(_) => "New entry created.".to_string(),
};
Ok(EventOutcome::DataSaved(outcome, message))
}
pub async fn revert_form(
app_state: &mut AppState,
path: &str,
grpc_client: &mut crate::services::grpc_client::GrpcClient,
) -> Result<EventOutcome> {
let message = logic::revert(app_state, path, grpc_client).await?;
Ok(EventOutcome::Ok(message))
}

View File

@@ -0,0 +1,39 @@
// src/pages/forms/loader.rs
use anyhow::{Context, Result};
use crate::{
state::app::state::AppState,
services::grpc_client::GrpcClient,
services::ui_service::UiService, // ✅ import UiService
config::binds::Config,
pages::forms::FormState,
};
pub async fn ensure_form_loaded_and_count(
grpc_client: &mut GrpcClient,
app_state: &mut AppState,
config: &Config,
profile: &str,
table: &str,
) -> Result<()> {
let path = format!("{}/{}", profile, table);
app_state.ensure_form_editor(&path, config, || {
FormState::new(profile.to_string(), table.to_string(), vec![])
});
if let Some(form_state) = app_state.form_state_for_path(&path) {
UiService::fetch_and_set_table_count(grpc_client, form_state)
.await
.context("Failed to fetch table count")?;
if form_state.total_count > 0 {
UiService::load_table_data_by_position(grpc_client, form_state)
.await
.context("Failed to load table data")?;
} else {
form_state.reset_to_empty();
}
}
Ok(())
}

View File

@@ -3,7 +3,11 @@
pub mod ui; pub mod ui;
pub mod state; pub mod state;
pub mod logic; pub mod logic;
pub mod event;
pub mod loader;
pub use ui::*; pub use ui::*;
pub use state::*; pub use state::*;
pub use logic::*; pub use logic::*;
pub use event::*;
pub use loader::*;

View File

@@ -16,6 +16,7 @@ use crate::pages::admin::AdminState;
use crate::pages::admin::AdminFocus; use crate::pages::admin::AdminFocus;
use crate::pages::intro::IntroState; use crate::pages::intro::IntroState;
use crate::pages::forms::{FormState, FieldDefinition}; use crate::pages::forms::{FormState, FieldDefinition};
use crate::pages::forms;
use crate::pages::routing::{Router, Page}; use crate::pages::routing::{Router, Page};
use crate::buffer::state::BufferState; use crate::buffer::state::BufferState;
use crate::buffer::state::AppView; use crate::buffer::state::AppView;
@@ -459,7 +460,7 @@ pub async fn run_ui() -> Result<()> {
} }
} }
if let Page::Form(current_path) = &router.current { if let Page::Form(_current_path) = &router.current {
let current_view_profile = app_state.current_view_profile_name.clone(); let current_view_profile = app_state.current_view_profile_name.clone();
let current_view_table = app_state.current_view_table_name.clone(); let current_view_table = app_state.current_view_table_name.clone();
@@ -475,52 +476,16 @@ pub async fn run_ui() -> Result<()> {
); );
needs_redraw = true; needs_redraw = true;
match UiService::load_table_view( // DELEGATE to the forms loader
match forms::loader::ensure_form_loaded_and_count(
&mut grpc_client, &mut grpc_client,
&mut app_state, &mut app_state,
&config,
prof_name, prof_name,
tbl_name, tbl_name,
) ).await {
.await Ok(()) => {
{ app_state.hide_dialog();
Ok(new_form_state) => {
// Set the new form state and fetch count
let path = format!("{}/{}", prof_name, tbl_name);
app_state.ensure_form_editor(&path, &config, || new_form_state);
if let Some(form_state) = app_state.form_state_for_path(&path) {
if let Err(e) = UiService::fetch_and_set_table_count(
&mut grpc_client,
form_state,
)
.await
{
app_state.update_dialog_content(
&format!("Error fetching count: {}", e),
vec!["OK".to_string()],
DialogPurpose::LoginFailed,
);
} else if form_state.total_count > 0 {
if let Err(e) = UiService::load_table_data_by_position(
&mut grpc_client,
form_state,
)
.await
{
app_state.update_dialog_content(
&format!("Error loading data: {}", e),
vec!["OK".to_string()],
DialogPurpose::LoginFailed,
);
} else {
app_state.hide_dialog();
}
} else {
form_state.reset_to_empty();
app_state.hide_dialog();
}
}
prev_view_profile_name = current_view_profile; prev_view_profile_name = current_view_profile;
prev_view_table_name = current_view_table; prev_view_table_name = current_view_table;
table_just_switched = true; table_just_switched = true;
@@ -531,10 +496,9 @@ pub async fn run_ui() -> Result<()> {
vec!["OK".to_string()], vec!["OK".to_string()],
DialogPurpose::LoginFailed, DialogPurpose::LoginFailed,
); );
app_state.current_view_profile_name = // Reset to previous state on error
prev_view_profile_name.clone(); app_state.current_view_profile_name = prev_view_profile_name.clone();
app_state.current_view_table_name = app_state.current_view_table_name = prev_view_table_name.clone();
prev_view_table_name.clone();
} }
} }
} }