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 active: bool,
pub input: String,

View File

@@ -36,6 +36,7 @@ use crate::pages::register::RegisterResult;
use crate::pages::routing::{Router, Page};
use crate::movement::MovementAction;
use crate::dialog;
use crate::pages::forms;
use crate::pages::forms::FormState;
use crate::pages::forms::logic::{save, revert, SaveOutcome};
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(
@@ -861,22 +870,11 @@ impl EventHandler {
.await?;
Ok(EventOutcome::Ok(message))
} else {
let save_outcome = if let Page::Form(path) = &router.current {
save(
app_state,
path,
&mut self.grpc_client,
)
.await?
if let Page::Form(path) = &router.current {
forms::event::save_form(app_state, path, &mut self.grpc_client).await
} else {
SaveOutcome::NoChange
};
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))
Ok(EventOutcome::Ok("Nothing to save".to_string()))
}
}
}
"force_quit" => {
@@ -899,18 +897,17 @@ impl EventHandler {
app_state,
)
.await?
} else {
let save_outcome = if let Page::Form(path) = &router.current {
save(app_state, path, &mut self.grpc_client).await?
} else {
SaveOutcome::NoChange
};
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 if let Page::Form(path) = &router.current {
let save_result = forms::event::save_form(app_state, path, &mut self.grpc_client).await?;
match save_result {
EventOutcome::DataSaved(_, msg) => msg,
EventOutcome::Ok(msg) => msg,
_ => "Saved".to_string(),
}
} else {
"No changes to save.".to_string()
};
if let Page::Form(path) = &router.current {
if let Some(editor) = app_state.editor_for_path(path) {
editor.cleanup_cursor()?;
@@ -933,7 +930,7 @@ impl EventHandler {
.await
} else {
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 {
"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 state;
pub mod logic;
pub mod event;
pub mod loader;
pub use ui::*;
pub use state::*;
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::intro::IntroState;
use crate::pages::forms::{FormState, FieldDefinition};
use crate::pages::forms;
use crate::pages::routing::{Router, Page};
use crate::buffer::state::BufferState;
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_table = app_state.current_view_table_name.clone();
@@ -475,52 +476,16 @@ pub async fn run_ui() -> Result<()> {
);
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 app_state,
&config,
prof_name,
tbl_name,
)
.await
{
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 {
).await {
Ok(()) => {
app_state.hide_dialog();
}
} else {
form_state.reset_to_empty();
app_state.hide_dialog();
}
}
prev_view_profile_name = current_view_profile;
prev_view_table_name = current_view_table;
table_just_switched = true;
@@ -531,10 +496,9 @@ pub async fn run_ui() -> Result<()> {
vec!["OK".to_string()],
DialogPurpose::LoginFailed,
);
app_state.current_view_profile_name =
prev_view_profile_name.clone();
app_state.current_view_table_name =
prev_view_table_name.clone();
// Reset to previous state on error
app_state.current_view_profile_name = prev_view_profile_name.clone();
app_state.current_view_table_name = prev_view_table_name.clone();
}
}
}