From 3081125716d4452325a0bda4725c85815903ad0e Mon Sep 17 00:00:00 2001 From: Priec Date: Tue, 2 Sep 2025 00:36:49 +0200 Subject: [PATCH] moving add_table to add_logic modern architecture2 --- client/src/dialog/logic.rs | 9 +- client/src/modes/handlers/event.rs | 18 ++ client/src/pages/admin/admin/state.rs | 2 - client/src/pages/admin/main/logic.rs | 16 +- .../src/pages/admin_panel/add_table/state.rs | 173 ------------------ client/src/ui/handlers/ui.rs | 15 +- 6 files changed, 38 insertions(+), 195 deletions(-) diff --git a/client/src/dialog/logic.rs b/client/src/dialog/logic.rs index 7954e5b..eee8ab8 100644 --- a/client/src/dialog/logic.rs +++ b/client/src/dialog/logic.rs @@ -154,15 +154,14 @@ pub async fn handle_dialog_event( DialogPurpose::ConfirmDeleteColumns => match selected_index { 0 => { // "Confirm" button selected - if let Page::Admin(state) = &mut router.current { - let outcome_message = - handle_delete_selected_columns(&mut state.add_table_state); + if let Page::AddTable(page) = &mut router.current { + let outcome_message = handle_delete_selected_columns(&mut page.state); app_state.hide_dialog(); return Some(Ok(EventOutcome::Ok(outcome_message))); } return Some(Ok(EventOutcome::Ok( - "Admin state not active".to_string(), - ))); + "AddTable page not active".to_string(), + ))); } 1 => { // "Cancel" button selected diff --git a/client/src/modes/handlers/event.rs b/client/src/modes/handlers/event.rs index 1ba3952..6737cb1 100644 --- a/client/src/modes/handlers/event.rs +++ b/client/src/modes/handlers/event.rs @@ -379,6 +379,24 @@ impl EventHandler { return Ok(outcome); } } else if let Page::AddTable(add_table_page) = &mut router.current { + // Allow ":" (enter_command_mode) even when inside AddTable canvas + if let Some(action) = + config.get_general_action(key_event.code, key_event.modifiers) + { + if action == "enter_command_mode" + && !self.command_mode + && !app_state.ui.show_search_palette + && !self.navigation_state.active + { + self.command_mode = true; + self.command_input.clear(); + self.command_message.clear(); + self.key_sequence_tracker.reset(); + app_state.ui.focus_outside_canvas = true; + return Ok(EventOutcome::Ok(String::new())); + } + } + // Handle AddTable before global actions so canvas gets first shot at keys. // Map keys to MovementAction (same as AddLogic early handler) let movement_action_early = if let Some(act) = diff --git a/client/src/pages/admin/admin/state.rs b/client/src/pages/admin/admin/state.rs index 5d4d384..ba53960 100644 --- a/client/src/pages/admin/admin/state.rs +++ b/client/src/pages/admin/admin/state.rs @@ -1,6 +1,5 @@ // src/pages/admin/admin/state.rs use ratatui::widgets::ListState; -use crate::pages::admin_panel::add_table::state::AddTableState; use crate::movement::{move_focus, MovementAction}; use crate::state::app::state::AppState; @@ -26,7 +25,6 @@ pub struct AdminState { pub selected_profile_index: Option, pub selected_table_index: Option, pub current_focus: AdminFocus, - pub add_table_state: AddTableState, } impl AdminState { diff --git a/client/src/pages/admin/main/logic.rs b/client/src/pages/admin/main/logic.rs index 8052bcb..91bd2cb 100644 --- a/client/src/pages/admin/main/logic.rs +++ b/client/src/pages/admin/main/logic.rs @@ -3,8 +3,8 @@ use crate::pages::admin::{AdminFocus, AdminState}; use crate::state::app::state::AppState; use crate::config::binds::config::Config; use crate::buffer::state::{BufferState, AppView}; -use crate::pages::admin_panel::add_table::state::{AddTableState, LinkDefinition}; use ratatui::widgets::ListState; +use crate::pages::admin_panel::add_table::state::{AddTableFormState, LinkDefinition}; use crate::pages::admin_panel::add_logic::state::{AddLogicState, AddLogicFocus, AddLogicFormState}; use crate::pages::routing::{Page, Router}; @@ -299,14 +299,16 @@ pub fn handle_admin_navigation( selected: false, }).collect(); - admin_state.add_table_state = AddTableState { - profile_name: selected_profile_name, - links: available_links, - ..AddTableState::default() // Reset other fields - }; + // Build decoupled AddTable page and route into it + let mut page = AddTableFormState::new(selected_profile_name.clone()); + page.state.links = available_links; + router.current = Page::AddTable(page); buffer_state.update_history(AppView::AddTable); app_state.ui.focus_outside_canvas = false; - *command_message = format!("Opening Add Table for profile '{}'...", admin_state.add_table_state.profile_name); + *command_message = format!( + "Opening Add Table for profile '{}'...", + selected_profile_name + ); handled = true; } else { *command_message = "Error: Selected profile index out of bounds.".to_string(); diff --git a/client/src/pages/admin_panel/add_table/state.rs b/client/src/pages/admin_panel/add_table/state.rs index df076c6..1135d92 100644 --- a/client/src/pages/admin_panel/add_table/state.rs +++ b/client/src/pages/admin_panel/add_table/state.rs @@ -4,7 +4,6 @@ use canvas::{DataProvider, AppMode}; use canvas::FormEditor; use ratatui::widgets::TableState; use serde::{Deserialize, Serialize}; -use crate::movement::{move_focus, MovementAction}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct ColumnDefinition { @@ -211,178 +210,6 @@ impl DataProvider for AddTableState { } } - -impl AddTableState { - pub fn handle_movement(&mut self, action: MovementAction) -> bool { - use AddTableFocus::*; - - // Linear outer focus order - const ORDER: [AddTableFocus; 10] = [ - InputTableName, - InputColumnName, - InputColumnType, - AddColumnButton, - ColumnsTable, - IndexesTable, - LinksTable, - SaveButton, - DeleteSelectedButton, - CancelButton, - ]; - - // Enter "inside" on Select from outer panes - match (self.current_focus, action) { - (ColumnsTable, MovementAction::Select) => { - if !self.columns.is_empty() && self.column_table_state.selected().is_none() { - self.column_table_state.select(Some(0)); - } - self.current_focus = InsideColumnsTable; - return true; - } - (IndexesTable, MovementAction::Select) => { - if !self.indexes.is_empty() && self.index_table_state.selected().is_none() { - self.index_table_state.select(Some(0)); - } - self.current_focus = InsideIndexesTable; - return true; - } - (LinksTable, MovementAction::Select) => { - if !self.links.is_empty() && self.link_table_state.selected().is_none() { - self.link_table_state.select(Some(0)); - } - self.current_focus = InsideLinksTable; - return true; - } - _ => {} - } - - // Handle "inside" states: Up/Down/Select/Esc; block outer movement keys - match self.current_focus { - InsideColumnsTable => { - match action { - MovementAction::Up => { - if let Some(i) = self.column_table_state.selected() { - let next = i.saturating_sub(1); - self.column_table_state.select(Some(next)); - } else if !self.columns.is_empty() { - self.column_table_state.select(Some(0)); - } - return true; - } - MovementAction::Down => { - if let Some(i) = self.column_table_state.selected() { - let last = self.columns.len().saturating_sub(1); - let next = if i < last { i + 1 } else { i }; - self.column_table_state.select(Some(next)); - } else if !self.columns.is_empty() { - self.column_table_state.select(Some(0)); - } - return true; - } - MovementAction::Select => { - if let Some(i) = self.column_table_state.selected() { - if let Some(col) = self.columns.get_mut(i) { - col.selected = !col.selected; - self.has_unsaved_changes = true; - } - } - return true; - } - MovementAction::Esc => { - self.column_table_state.select(None); - self.current_focus = ColumnsTable; - return true; - } - MovementAction::Next | MovementAction::Previous => return true, // block outer moves - _ => {} - } - } - InsideIndexesTable => { - match action { - MovementAction::Up => { - if let Some(i) = self.index_table_state.selected() { - let next = i.saturating_sub(1); - self.index_table_state.select(Some(next)); - } else if !self.indexes.is_empty() { - self.index_table_state.select(Some(0)); - } - return true; - } - MovementAction::Down => { - if let Some(i) = self.index_table_state.selected() { - let last = self.indexes.len().saturating_sub(1); - let next = if i < last { i + 1 } else { i }; - self.index_table_state.select(Some(next)); - } else if !self.indexes.is_empty() { - self.index_table_state.select(Some(0)); - } - return true; - } - MovementAction::Select => { - if let Some(i) = self.index_table_state.selected() { - if let Some(ix) = self.indexes.get_mut(i) { - ix.selected = !ix.selected; - self.has_unsaved_changes = true; - } - } - return true; - } - MovementAction::Esc => { - self.index_table_state.select(None); - self.current_focus = IndexesTable; - return true; - } - MovementAction::Next | MovementAction::Previous => return true, // block outer moves - _ => {} - } - } - InsideLinksTable => { - match action { - MovementAction::Up => { - if let Some(i) = self.link_table_state.selected() { - let next = i.saturating_sub(1); - self.link_table_state.select(Some(next)); - } else if !self.links.is_empty() { - self.link_table_state.select(Some(0)); - } - return true; - } - MovementAction::Down => { - if let Some(i) = self.link_table_state.selected() { - let last = self.links.len().saturating_sub(1); - let next = if i < last { i + 1 } else { i }; - self.link_table_state.select(Some(next)); - } else if !self.links.is_empty() { - self.link_table_state.select(Some(0)); - } - return true; - } - MovementAction::Select => { - if let Some(i) = self.link_table_state.selected() { - if let Some(link) = self.links.get_mut(i) { - link.selected = !link.selected; - self.has_unsaved_changes = true; - } - } - return true; - } - MovementAction::Esc => { - self.link_table_state.select(None); - self.current_focus = LinksTable; - return true; - } - MovementAction::Next | MovementAction::Previous => return true, // block outer moves - _ => {} - } - } - _ => {} - } - - // Default: outer navigation via helper - move_focus(&ORDER, &mut self.current_focus, action) - } -} - pub struct AddTableFormState { pub state: AddTableState, pub editor: FormEditor, diff --git a/client/src/ui/handlers/ui.rs b/client/src/ui/handlers/ui.rs index 33e0aac..5f19473 100644 --- a/client/src/ui/handlers/ui.rs +++ b/client/src/ui/handlers/ui.rs @@ -366,7 +366,9 @@ pub async fn run_ui() -> Result<()> { vec!["OK".to_string()], DialogPurpose::SaveTableSuccess, ); - admin_state.add_table_state.has_unsaved_changes = false; + if let Page::AddTable(page) = &mut router.current { + page.state.has_unsaved_changes = false; + } } Err(e) => { event_handler.command_message = format!("Save failed: {}", e); @@ -426,14 +428,11 @@ pub async fn run_ui() -> Result<()> { router.navigate(Page::Admin(admin_state.clone())); } AppView::AddTable => { - if let Page::AddTable(_) = &router.current { - } else { - let mut page = - add_table::state::AddTableFormState::from_state( - admin_state.add_table_state.clone(), - ); + if let Page::AddTable(page) = &mut router.current { + // Ensure keymap is set once (same as AddLogic) page.editor.set_keymap(config.build_canvas_keymap()); - router.navigate(Page::AddTable(page)); + } else { + // Page is created by admin navigation (Button2). No-op here. } } AppView::AddLogic => {