compiled successfulywith rich suggestions now
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
use crate::state::pages::canvas_state::CanvasState;
|
use crate::state::pages::canvas_state::CanvasState;
|
||||||
|
|
||||||
// NEW
|
// NEW
|
||||||
use canvas::CanvasState;
|
use canvas::canvas::CanvasState;
|
||||||
```
|
```
|
||||||
|
|
||||||
**Files that need updating:**
|
**Files that need updating:**
|
||||||
@@ -84,7 +84,7 @@ The canvas crate expects a `CanvasTheme` trait. You need to implement this for y
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
// In client/src/config/colors/themes.rs
|
// In client/src/config/colors/themes.rs
|
||||||
use canvas::CanvasTheme;
|
use canvas::canvas::CanvasTheme;
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
|
|
||||||
impl CanvasTheme for Theme {
|
impl CanvasTheme for Theme {
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ impl CanvasState for MyForm {
|
|||||||
CanvasAction::SelectSuggestion => {
|
CanvasAction::SelectSuggestion => {
|
||||||
if let Some(suggestion) = self.suggestions.get_selected() {
|
if let Some(suggestion) = self.suggestions.get_selected() {
|
||||||
*self.get_current_input_mut() = suggestion.clone();
|
*self.get_current_input_mut() = suggestion.clone();
|
||||||
self.deactivate_suggestions();
|
self.deactivate_autocomplete();
|
||||||
Some("Applied suggestion".to_string())
|
Some("Applied suggestion".to_string())
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ pub fn render_form(
|
|||||||
table_name: &str,
|
table_name: &str,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
is_edit_mode: bool,
|
is_edit_mode: bool,
|
||||||
highlight_state: &HighlightState, // Now using canvas::HighlightState
|
highlight_state: &HighlightState,
|
||||||
total_count: u64,
|
total_count: u64,
|
||||||
current_position: u64,
|
current_position: u64,
|
||||||
) {
|
) {
|
||||||
@@ -56,6 +56,7 @@ pub fn render_form(
|
|||||||
total_count, current_position, total_count
|
total_count, current_position, total_count
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let count_para = Paragraph::new(count_position_text)
|
let count_para = Paragraph::new(count_position_text)
|
||||||
.style(Style::default().fg(theme.fg))
|
.style(Style::default().fg(theme.fg))
|
||||||
.alignment(Alignment::Left);
|
.alignment(Alignment::Left);
|
||||||
@@ -71,11 +72,13 @@ pub fn render_form(
|
|||||||
highlight_state,
|
highlight_state,
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- RENDER AUTOCOMPLETE ---
|
// --- RENDER RICH AUTOCOMPLETE ONLY ---
|
||||||
if form_state.autocomplete_active {
|
if form_state.autocomplete_active {
|
||||||
if let Some(active_rect) = active_field_rect {
|
if let Some(active_rect) = active_field_rect {
|
||||||
let selected_index = form_state.get_selected_suggestion_index();
|
// Get selected index directly from form_state
|
||||||
|
let selected_index = form_state.selected_suggestion_index;
|
||||||
|
|
||||||
|
// Only render rich suggestions (your Hit objects)
|
||||||
if let Some(rich_suggestions) = form_state.get_rich_suggestions() {
|
if let Some(rich_suggestions) = form_state.get_rich_suggestions() {
|
||||||
if !rich_suggestions.is_empty() {
|
if !rich_suggestions.is_empty() {
|
||||||
autocomplete::render_hit_autocomplete_dropdown(
|
autocomplete::render_hit_autocomplete_dropdown(
|
||||||
@@ -89,18 +92,7 @@ pub fn render_form(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if let Some(simple_suggestions) = form_state.get_suggestions() {
|
// Removed simple suggestions - we only use rich ones now!
|
||||||
if !simple_suggestions.is_empty() {
|
|
||||||
autocomplete::render_autocomplete_dropdown(
|
|
||||||
f,
|
|
||||||
active_rect,
|
|
||||||
f.area(),
|
|
||||||
theme,
|
|
||||||
simple_suggestions,
|
|
||||||
selected_index,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use ratatui::{
|
|||||||
use crate::config::colors::themes::Theme;
|
use crate::config::colors::themes::Theme;
|
||||||
use crate::state::app::highlight::HighlightState;
|
use crate::state::app::highlight::HighlightState;
|
||||||
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
||||||
use canvas::CanvasState as LibraryCanvasState;
|
use canvas::canvas::CanvasState as LibraryCanvasState;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
|
||||||
/// Render canvas for legacy CanvasState (AddTableState, LoginState, RegisterState, AddLogicState)
|
/// Render canvas for legacy CanvasState (AddTableState, LoginState, RegisterState, AddLogicState)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// src/config/colors/themes.rs
|
// src/config/colors/themes.rs
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
use canvas::CanvasTheme;
|
use canvas::canvas::CanvasTheme;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::tui::functions::common::form::{revert, save};
|
|||||||
use crate::tui::functions::common::form::SaveOutcome;
|
use crate::tui::functions::common::form::SaveOutcome;
|
||||||
use crate::modes::handlers::event::EventOutcome;
|
use crate::modes::handlers::event::EventOutcome;
|
||||||
use crossterm::event::{KeyCode, KeyEvent};
|
use crossterm::event::{KeyCode, KeyEvent};
|
||||||
use canvas::CanvasState;
|
use canvas::canvas::CanvasState;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/functions/modes/read_only/form_ro.rs
|
// src/functions/modes/read_only/form_ro.rs
|
||||||
|
|
||||||
use crate::config::binds::key_sequences::KeySequenceTracker;
|
use crate::config::binds::key_sequences::KeySequenceTracker;
|
||||||
use canvas::CanvasState;
|
use canvas::canvas::CanvasState;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use crate::state::pages::{
|
|||||||
auth::{LoginState, RegisterState},
|
auth::{LoginState, RegisterState},
|
||||||
form::FormState,
|
form::FormState,
|
||||||
};
|
};
|
||||||
use canvas::CanvasState;
|
use canvas::canvas::CanvasState;
|
||||||
use canvas::{CanvasAction, ActionDispatcher, ActionResult};
|
use canvas::{canvas::CanvasAction, dispatcher::ActionDispatcher, canvas::ActionResult};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::proto::komp_ac::search::search_response::Hit;
|
use common::proto::komp_ac::search::search_response::Hit;
|
||||||
use crossterm::event::{KeyCode, KeyEvent};
|
use crossterm::event::{KeyCode, KeyEvent};
|
||||||
@@ -170,7 +170,7 @@ pub async fn handle_edit_event(
|
|||||||
return Ok(EditEventOutcome::Message(String::new()));
|
return Ok(EditEventOutcome::Message(String::new()));
|
||||||
}
|
}
|
||||||
"exit" => {
|
"exit" => {
|
||||||
form_state.deactivate_suggestions();
|
form_state.deactivate_autocomplete();
|
||||||
return Ok(EditEventOutcome::Message(
|
return Ok(EditEventOutcome::Message(
|
||||||
"Autocomplete cancelled".to_string(),
|
"Autocomplete cancelled".to_string(),
|
||||||
));
|
));
|
||||||
@@ -202,14 +202,14 @@ pub async fn handle_edit_event(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 4. Finalize state
|
// 4. Finalize state
|
||||||
form_state.deactivate_suggestions();
|
form_state.deactivate_autocomplete();
|
||||||
form_state.set_has_unsaved_changes(true);
|
form_state.set_has_unsaved_changes(true);
|
||||||
return Ok(EditEventOutcome::Message(
|
return Ok(EditEventOutcome::Message(
|
||||||
"Selection made".to_string(),
|
"Selection made".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
form_state.deactivate_suggestions();
|
form_state.deactivate_autocomplete();
|
||||||
// Fall through to default 'enter' behavior
|
// Fall through to default 'enter' behavior
|
||||||
}
|
}
|
||||||
_ => {} // Let other keys fall through to the live search logic
|
_ => {} // Let other keys fall through to the live search logic
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::state::pages::add_logic::AddLogicState;
|
|||||||
use crate::state::pages::add_table::AddTableState;
|
use crate::state::pages::add_table::AddTableState;
|
||||||
use crate::state::app::state::AppState;
|
use crate::state::app::state::AppState;
|
||||||
use crate::functions::modes::read_only::{add_logic_ro, auth_ro, form_ro, add_table_ro};
|
use crate::functions::modes::read_only::{add_logic_ro, auth_ro, form_ro, add_table_ro};
|
||||||
use canvas::{CanvasAction, ActionDispatcher, ActionResult};
|
use canvas::{canvas::CanvasAction, dispatcher::ActionDispatcher, canvas::ActionResult};
|
||||||
use crossterm::event::KeyEvent;
|
use crossterm::event::KeyEvent;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ pub async fn handle_read_only_event(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle FormState (uses library CanvasState)
|
// Handle FormState (uses library CanvasState)
|
||||||
use canvas::CanvasState as LibraryCanvasState; // Import at the top of the function
|
use canvas::canvas::CanvasState as LibraryCanvasState; // Import at the top of the function
|
||||||
let current_input = form_state.get_current_input();
|
let current_input = form_state.get_current_input();
|
||||||
let current_pos = form_state.current_cursor_pos();
|
let current_pos = form_state.current_cursor_pos();
|
||||||
if !current_input.is_empty() && current_pos < current_input.len() {
|
if !current_input.is_empty() && current_pos < current_input.len() {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ use crate::modes::{
|
|||||||
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
||||||
use crate::services::auth::AuthClient;
|
use crate::services::auth::AuthClient;
|
||||||
use crate::services::grpc_client::GrpcClient;
|
use crate::services::grpc_client::GrpcClient;
|
||||||
use canvas::{CanvasAction, ActionDispatcher};
|
use canvas::{canvas::CanvasAction, dispatcher::ActionDispatcher};
|
||||||
use canvas::CanvasState as LibraryCanvasState;
|
use canvas::canvas::CanvasState as LibraryCanvasState;
|
||||||
use super::event_helper::*;
|
use super::event_helper::*;
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
app::{
|
app::{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::state::pages::{
|
|||||||
auth::{LoginState, RegisterState},
|
auth::{LoginState, RegisterState},
|
||||||
};
|
};
|
||||||
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
use crate::state::pages::canvas_state::CanvasState as LegacyCanvasState;
|
||||||
use canvas::CanvasState as LibraryCanvasState;
|
use canvas::canvas::CanvasState as LibraryCanvasState;
|
||||||
|
|
||||||
/// Get the current field index from the appropriate state based on which UI is active
|
/// Get the current field index from the appropriate state based on which UI is active
|
||||||
pub fn get_current_field_for_state(
|
pub fn get_current_field_for_state(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/state/pages/form.rs
|
// src/state/pages/form.rs
|
||||||
|
|
||||||
use crate::config::colors::themes::Theme;
|
use crate::config::colors::themes::Theme;
|
||||||
use canvas::{CanvasState, CanvasAction, ActionContext, HighlightState};
|
use canvas::canvas::{CanvasState, CanvasAction, ActionContext, HighlightState};
|
||||||
use common::proto::komp_ac::search::search_response::Hit;
|
use common::proto::komp_ac::search::search_response::Hit;
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
use ratatui::Frame;
|
use ratatui::Frame;
|
||||||
@@ -44,6 +44,14 @@ pub struct FormState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FormState {
|
impl FormState {
|
||||||
|
// Add this method
|
||||||
|
pub fn deactivate_autocomplete(&mut self) {
|
||||||
|
self.autocomplete_active = false;
|
||||||
|
self.autocomplete_suggestions.clear();
|
||||||
|
self.selected_suggestion_index = None;
|
||||||
|
self.autocomplete_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
profile_name: String,
|
profile_name: String,
|
||||||
table_name: String,
|
table_name: String,
|
||||||
@@ -145,7 +153,7 @@ impl FormState {
|
|||||||
} else {
|
} else {
|
||||||
self.current_position = 1;
|
self.current_position = 1;
|
||||||
}
|
}
|
||||||
self.deactivate_suggestions();
|
self.deactivate_autocomplete();
|
||||||
self.link_display_map.clear();
|
self.link_display_map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +212,7 @@ impl FormState {
|
|||||||
self.has_unsaved_changes = false;
|
self.has_unsaved_changes = false;
|
||||||
self.current_field = 0;
|
self.current_field = 0;
|
||||||
self.current_cursor_pos = 0;
|
self.current_cursor_pos = 0;
|
||||||
self.deactivate_suggestions();
|
self.deactivate_autocomplete();
|
||||||
self.link_display_map.clear();
|
self.link_display_map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +269,7 @@ impl CanvasState for FormState {
|
|||||||
if index < self.fields.len() {
|
if index < self.fields.len() {
|
||||||
self.current_field = index;
|
self.current_field = index;
|
||||||
}
|
}
|
||||||
self.deactivate_suggestions();
|
self.deactivate_autocomplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_current_cursor_pos(&mut self, pos: usize) {
|
fn set_current_cursor_pos(&mut self, pos: usize) {
|
||||||
@@ -272,38 +280,6 @@ impl CanvasState for FormState {
|
|||||||
self.has_unsaved_changes = changed;
|
self.has_unsaved_changes = changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- CANVAS CRATE SUGGESTIONS SUPPORT ---
|
|
||||||
fn get_suggestions(&self) -> Option<&[String]> {
|
|
||||||
None // We use rich suggestions instead
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_selected_suggestion_index(&self) -> Option<usize> {
|
|
||||||
if self.autocomplete_active {
|
|
||||||
self.selected_suggestion_index
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_selected_suggestion_index(&mut self, index: Option<usize>) {
|
|
||||||
if self.autocomplete_active {
|
|
||||||
self.selected_suggestion_index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn activate_suggestions(&mut self, suggestions: Vec<String>) {
|
|
||||||
// For compatibility - convert to rich format if needed
|
|
||||||
self.autocomplete_active = true;
|
|
||||||
self.selected_suggestion_index = if suggestions.is_empty() { None } else { Some(0) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deactivate_suggestions(&mut self) {
|
|
||||||
self.autocomplete_active = false;
|
|
||||||
self.autocomplete_suggestions.clear();
|
|
||||||
self.selected_suggestion_index = None;
|
|
||||||
self.autocomplete_loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- FEATURE-SPECIFIC ACTION HANDLING ---
|
// --- FEATURE-SPECIFIC ACTION HANDLING ---
|
||||||
fn handle_feature_action(&mut self, action: &CanvasAction, _context: &ActionContext) -> Option<String> {
|
fn handle_feature_action(&mut self, action: &CanvasAction, _context: &ActionContext) -> Option<String> {
|
||||||
match action {
|
match action {
|
||||||
@@ -319,7 +295,7 @@ impl CanvasState for FormState {
|
|||||||
*self.get_current_input_mut() = new_value.clone();
|
*self.get_current_input_mut() = new_value.clone();
|
||||||
self.set_current_cursor_pos(new_value.len());
|
self.set_current_cursor_pos(new_value.len());
|
||||||
self.set_has_unsaved_changes(true);
|
self.set_has_unsaved_changes(true);
|
||||||
self.deactivate_suggestions();
|
self.deactivate_autocomplete();
|
||||||
return Some(format!("Selected: {}", display_name));
|
return Some(format!("Selected: {}", display_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/tui/functions/form.rs
|
// src/tui/functions/form.rs
|
||||||
use crate::state::pages::form::FormState;
|
use crate::state::pages::form::FormState;
|
||||||
use crate::services::grpc_client::GrpcClient;
|
use crate::services::grpc_client::GrpcClient;
|
||||||
use canvas::CanvasState;
|
use canvas::canvas::CanvasState;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
pub async fn handle_action(
|
pub async fn handle_action(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use crate::modes::general::command_navigation::NavigationState;
|
|||||||
use crate::state::pages::canvas_state::CanvasState;
|
use crate::state::pages::canvas_state::CanvasState;
|
||||||
use crate::state::app::buffer::BufferState;
|
use crate::state::app::buffer::BufferState;
|
||||||
use crate::state::app::highlight::HighlightState as LocalHighlightState; // CHANGED: Alias local version
|
use crate::state::app::highlight::HighlightState as LocalHighlightState; // CHANGED: Alias local version
|
||||||
use canvas::HighlightState as CanvasHighlightState; // CHANGED: Import canvas version with alias
|
use canvas::canvas::HighlightState as CanvasHighlightState; // CHANGED: Import canvas version with alias
|
||||||
use crate::state::app::state::AppState;
|
use crate::state::app::state::AppState;
|
||||||
use crate::state::pages::admin::AdminState;
|
use crate::state::pages::admin::AdminState;
|
||||||
use crate::state::pages::auth::AuthState;
|
use crate::state::pages::auth::AuthState;
|
||||||
|
|||||||
Reference in New Issue
Block a user