add table and add logic removal from ui.rs and event.rs
This commit is contained in:
@@ -460,22 +460,6 @@ impl EventHandler {
|
|||||||
// Let the current page handle decoupled movement first
|
// Let the current page handle decoupled movement first
|
||||||
if let Some(ma) = movement_action {
|
if let Some(ma) = movement_action {
|
||||||
match &mut router.current {
|
match &mut router.current {
|
||||||
// LOGIN: From buttons (general) back into the canvas with 'k' (Up),
|
|
||||||
// but ONLY from the left-most "Login" button.
|
|
||||||
Page::AddTable(state) => {
|
|
||||||
if state.handle_movement(ma) {
|
|
||||||
// Keep UI focus consistent with inputs vs. outer elements
|
|
||||||
use crate::pages::admin_panel::add_table::state::AddTableFocus;
|
|
||||||
let is_canvas_input = matches!(
|
|
||||||
state.current_focus,
|
|
||||||
AddTableFocus::InputTableName
|
|
||||||
| AddTableFocus::InputColumnName
|
|
||||||
| AddTableFocus::InputColumnType
|
|
||||||
);
|
|
||||||
app_state.ui.focus_outside_canvas = !is_canvas_input;
|
|
||||||
return Ok(EventOutcome::Ok(String::new()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Page::Intro(state) => {
|
Page::Intro(state) => {
|
||||||
if state.handle_movement(ma) {
|
if state.handle_movement(ma) {
|
||||||
return Ok(EventOutcome::Ok(String::new()));
|
return Ok(EventOutcome::Ok(String::new()));
|
||||||
@@ -506,8 +490,9 @@ impl EventHandler {
|
|||||||
if let Page::AddTable(add_table_state) = &mut router.current {
|
if let Page::AddTable(add_table_state) = &mut router.current {
|
||||||
let client_clone = self.grpc_client.clone();
|
let client_clone = self.grpc_client.clone();
|
||||||
let sender_clone = self.save_table_result_sender.clone();
|
let sender_clone = self.save_table_result_sender.clone();
|
||||||
if add_table::nav::handle_add_table_navigation(
|
if crate::pages::admin_panel::add_table::event::handle_add_table_event(
|
||||||
key_event,
|
key_event,
|
||||||
|
movement_action, // wrapper handles both movement + nav
|
||||||
config,
|
config,
|
||||||
app_state,
|
app_state,
|
||||||
add_table_state,
|
add_table_state,
|
||||||
@@ -515,9 +500,7 @@ impl EventHandler {
|
|||||||
sender_clone,
|
sender_clone,
|
||||||
&mut self.command_message,
|
&mut self.command_message,
|
||||||
) {
|
) {
|
||||||
return Ok(EventOutcome::Ok(
|
return Ok(EventOutcome::Ok(self.command_message.clone()));
|
||||||
self.command_message.clone(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
108
client/src/pages/admin_panel/add_logic/loader.rs
Normal file
108
client/src/pages/admin_panel/add_logic/loader.rs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// src/pages/admin_panel/add_logic/loader.rs
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
|
use crate::pages::admin_panel::add_logic::state::AddLogicState;
|
||||||
|
use crate::pages::routing::{Page, Router};
|
||||||
|
use crate::services::grpc_client::GrpcClient;
|
||||||
|
use crate::services::ui_service::UiService;
|
||||||
|
use crate::state::app::state::AppState;
|
||||||
|
|
||||||
|
/// Process pending table structure fetch for AddLogic page.
|
||||||
|
/// Returns true if UI needs a redraw.
|
||||||
|
pub async fn process_pending_table_structure_fetch(
|
||||||
|
app_state: &mut AppState,
|
||||||
|
router: &mut Router,
|
||||||
|
grpc_client: &mut GrpcClient,
|
||||||
|
command_message: &mut String,
|
||||||
|
) -> Result<bool> {
|
||||||
|
let mut needs_redraw = false;
|
||||||
|
|
||||||
|
if let Some((profile_name, table_name)) = app_state.pending_table_structure_fetch.take() {
|
||||||
|
if let Page::AddLogic(state) = &mut router.current {
|
||||||
|
if state.profile_name == profile_name
|
||||||
|
&& state.selected_table_name.as_deref() == Some(table_name.as_str())
|
||||||
|
{
|
||||||
|
info!(
|
||||||
|
"Fetching table structure for {}.{}",
|
||||||
|
profile_name, table_name
|
||||||
|
);
|
||||||
|
|
||||||
|
let fetch_message = UiService::initialize_add_logic_table_data(
|
||||||
|
grpc_client,
|
||||||
|
state,
|
||||||
|
&app_state.profile_tree,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
error!(
|
||||||
|
"Error initializing add_logic_table_data for {}.{}: {}",
|
||||||
|
profile_name, table_name, e
|
||||||
|
);
|
||||||
|
format!("Error fetching table structure: {}", e)
|
||||||
|
});
|
||||||
|
|
||||||
|
if !fetch_message.contains("Error") && !fetch_message.contains("Warning") {
|
||||||
|
info!("{}", fetch_message);
|
||||||
|
} else {
|
||||||
|
*command_message = fetch_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
needs_redraw = true;
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Mismatch in pending_table_structure_fetch: app_state wants {}.{}, \
|
||||||
|
but AddLogic state is for {}.{:?}",
|
||||||
|
profile_name, table_name, state.profile_name, state.selected_table_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Pending table structure fetch for {}.{} but AddLogic view is not active. Ignored.",
|
||||||
|
profile_name, table_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(needs_redraw)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the AddLogic page is awaiting columns for a selected table in the script editor,
|
||||||
|
/// fetch them and update the state. Returns true if UI needs a redraw.
|
||||||
|
pub async fn maybe_fetch_columns_for_awaiting_table(
|
||||||
|
grpc_client: &mut GrpcClient,
|
||||||
|
state: &mut AddLogicState,
|
||||||
|
command_message: &mut String,
|
||||||
|
) -> Result<bool> {
|
||||||
|
if let Some(table_name) = state
|
||||||
|
.script_editor_awaiting_column_autocomplete
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
|
let profile_name = state.profile_name.clone();
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Fetching columns for table selection: {}.{}",
|
||||||
|
profile_name, table_name
|
||||||
|
);
|
||||||
|
match UiService::fetch_columns_for_table(grpc_client, &profile_name, &table_name).await {
|
||||||
|
Ok(columns) => {
|
||||||
|
state.set_columns_for_table_autocomplete(columns.clone());
|
||||||
|
info!("Loaded {} columns for table '{}'", columns.len(), table_name);
|
||||||
|
*command_message =
|
||||||
|
format!("Columns for '{}' loaded. Select a column.", table_name);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"Failed to fetch columns for {}.{}: {}",
|
||||||
|
profile_name, table_name, e
|
||||||
|
);
|
||||||
|
state.script_editor_awaiting_column_autocomplete = None;
|
||||||
|
state.deactivate_script_editor_autocomplete();
|
||||||
|
*command_message = format!("Error loading columns for '{}': {}", table_name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@
|
|||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod nav;
|
pub mod nav;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
pub mod loader;
|
||||||
|
|||||||
51
client/src/pages/admin_panel/add_table/event.rs
Normal file
51
client/src/pages/admin_panel/add_table/event.rs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// src/pages/admin_panel/add_table/event.rs
|
||||||
|
|
||||||
|
use crate::config::binds::config::Config;
|
||||||
|
use crate::movement::MovementAction;
|
||||||
|
use crate::pages::admin_panel::add_table::nav;
|
||||||
|
use crate::pages::admin_panel::add_table::nav::SaveTableResultSender;
|
||||||
|
use crate::pages::admin_panel::add_table::state::{AddTableFocus, AddTableState};
|
||||||
|
use crate::services::GrpcClient;
|
||||||
|
use crate::state::app::state::AppState;
|
||||||
|
use crossterm::event::KeyEvent;
|
||||||
|
|
||||||
|
/// Handle all AddTable page-specific events in one place.
|
||||||
|
/// - First try movement actions (Up/Down/Select/Esc) via AddTableState::handle_movement
|
||||||
|
/// - Then, if not handled, try rich actions via nav::handle_add_table_navigation
|
||||||
|
///
|
||||||
|
/// Returns true if the key was handled (caller should stop propagation).
|
||||||
|
pub fn handle_add_table_event(
|
||||||
|
key_event: KeyEvent,
|
||||||
|
movement_action: Option<MovementAction>,
|
||||||
|
config: &Config,
|
||||||
|
app_state: &mut AppState,
|
||||||
|
state: &mut AddTableState,
|
||||||
|
grpc_client: GrpcClient,
|
||||||
|
save_result_sender: SaveTableResultSender,
|
||||||
|
command_message: &mut String,
|
||||||
|
) -> bool {
|
||||||
|
// 1) Try movement first (keeps focus cycling consistent)
|
||||||
|
if let Some(ma) = movement_action {
|
||||||
|
if state.handle_movement(ma) {
|
||||||
|
let is_canvas_input = matches!(
|
||||||
|
state.current_focus,
|
||||||
|
AddTableFocus::InputTableName
|
||||||
|
| AddTableFocus::InputColumnName
|
||||||
|
| AddTableFocus::InputColumnType
|
||||||
|
);
|
||||||
|
app_state.ui.focus_outside_canvas = !is_canvas_input;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Rich actions/navigation for AddTable
|
||||||
|
nav::handle_add_table_navigation(
|
||||||
|
key_event,
|
||||||
|
config,
|
||||||
|
app_state,
|
||||||
|
state,
|
||||||
|
grpc_client,
|
||||||
|
save_result_sender,
|
||||||
|
command_message,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -4,3 +4,4 @@ pub mod ui;
|
|||||||
pub mod nav;
|
pub mod nav;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod logic;
|
pub mod logic;
|
||||||
|
pub mod event;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crate::state::pages::auth::AuthState;
|
|||||||
use crate::state::pages::auth::UserRole;
|
use crate::state::pages::auth::UserRole;
|
||||||
use crate::pages::login::LoginFormState;
|
use crate::pages::login::LoginFormState;
|
||||||
use crate::pages::register::RegisterFormState;
|
use crate::pages::register::RegisterFormState;
|
||||||
|
use crate::pages::admin_panel::add_logic;
|
||||||
use crate::pages::admin::AdminState;
|
use crate::pages::admin::AdminState;
|
||||||
use crate::pages::admin::AdminFocus;
|
use crate::pages::admin::AdminFocus;
|
||||||
use crate::pages::admin::admin;
|
use crate::pages::admin::admin;
|
||||||
@@ -485,67 +486,25 @@ pub async fn run_ui() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue with the rest of the positioning logic...
|
let needs_redraw_from_fetch = add_logic::loader::process_pending_table_structure_fetch(
|
||||||
// Now we can use CanvasState methods like get_current_input(), current_field(), etc.
|
&mut app_state,
|
||||||
|
&mut router,
|
||||||
|
&mut grpc_client,
|
||||||
|
&mut event_handler.command_message,
|
||||||
|
).await.unwrap_or(false);
|
||||||
|
|
||||||
if let Some((profile_name, table_name)) = app_state.pending_table_structure_fetch.take() {
|
if needs_redraw_from_fetch {
|
||||||
if let Page::AddLogic(state) = &mut router.current {
|
needs_redraw = true;
|
||||||
if state.profile_name == profile_name
|
|
||||||
&& state.selected_table_name.as_deref() == Some(table_name.as_str())
|
|
||||||
{
|
|
||||||
info!("Fetching table structure for {}.{}", profile_name, table_name);
|
|
||||||
let fetch_message = UiService::initialize_add_logic_table_data(
|
|
||||||
&mut grpc_client,
|
|
||||||
state,
|
|
||||||
&app_state.profile_tree,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
error!("Error initializing add_logic_table_data: {}", e);
|
|
||||||
format!("Error fetching table structure: {}", e)
|
|
||||||
});
|
|
||||||
|
|
||||||
if !fetch_message.contains("Error") && !fetch_message.contains("Warning") {
|
|
||||||
info!("{}", fetch_message);
|
|
||||||
} else {
|
|
||||||
event_handler.command_message = fetch_message;
|
|
||||||
}
|
|
||||||
needs_redraw = true;
|
|
||||||
} else {
|
|
||||||
error!(
|
|
||||||
"Mismatch in pending_table_structure_fetch: app_state wants {}.{}, but AddLogic state is for {}.{:?}",
|
|
||||||
profile_name,
|
|
||||||
table_name,
|
|
||||||
state.profile_name,
|
|
||||||
state.selected_table_name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!(
|
|
||||||
"Pending table structure fetch for {}.{} but AddLogic view is not active. Fetch ignored.",
|
|
||||||
profile_name, table_name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Page::AddLogic(state) = &mut router.current {
|
if let Page::AddLogic(state) = &mut router.current {
|
||||||
if let Some(table_name) = state.script_editor_awaiting_column_autocomplete.clone() {
|
let needs_redraw_from_columns = add_logic::loader::maybe_fetch_columns_for_awaiting_table(
|
||||||
let profile_name = state.profile_name.clone();
|
&mut grpc_client,
|
||||||
|
state,
|
||||||
|
&mut event_handler.command_message,
|
||||||
|
).await.unwrap_or(false);
|
||||||
|
|
||||||
info!("Fetching columns for table selection: {}.{}", profile_name, table_name);
|
if needs_redraw_from_columns {
|
||||||
match UiService::fetch_columns_for_table(&mut grpc_client, &profile_name, &table_name).await {
|
|
||||||
Ok(columns) => {
|
|
||||||
state.set_columns_for_table_autocomplete(columns.clone());
|
|
||||||
info!("Loaded {} columns for table '{}'", columns.len(), table_name);
|
|
||||||
event_handler.command_message = format!("Columns for '{}' loaded. Select a column.", table_name);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Failed to fetch columns for {}.{}: {}", profile_name, table_name, e);
|
|
||||||
state.script_editor_awaiting_column_autocomplete = None;
|
|
||||||
state.deactivate_script_editor_autocomplete();
|
|
||||||
event_handler.command_message = format!("Error loading columns for '{}': {}", table_name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
needs_redraw = true;
|
needs_redraw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user