grpc post request to the table definition from add table, not working, major bug, needs debugging to make it work

This commit is contained in:
filipriec
2025-04-22 23:22:59 +02:00
parent 2992f122bc
commit 6fa8b06063
5 changed files with 156 additions and 5 deletions

View File

@@ -6,8 +6,14 @@ use crate::state::{
};
use crossterm::event::{KeyEvent};
use ratatui::widgets::TableState;
use crate::tui::functions::common::add_table::handle_add_column_action;
use crate::tui::functions::common::add_table::{handle_add_column_action, handle_save_table_action};
use crate::ui::handlers::context::DialogPurpose;
use crate::services::GrpcClient;
use tokio::sync::mpsc;
use anyhow::Result;
// Define a type for the save result channel
pub type SaveTableResultSender = mpsc::Sender<Result<String>>;
/// Handles navigation events specifically for the Add Table view.
/// Returns true if the event was handled, false otherwise.
@@ -16,6 +22,8 @@ pub fn handle_add_table_navigation(
config: &Config,
app_state: &mut AppState,
add_table_state: &mut AddTableState,
grpc_client: GrpcClient,
save_result_sender: SaveTableResultSender,
command_message: &mut String,
) -> bool {
let action = config.get_general_action(key.code, key.modifiers);
@@ -246,8 +254,25 @@ pub fn handle_add_table_navigation(
}
}
AddTableFocus::SaveButton => {
*command_message = "Action: Save Table (Not Implemented)".to_string();
// TODO: Implement logic
// --- Initiate Async Save ---
if add_table_state.table_name.is_empty() {
*command_message = "Cannot save: Table name is empty.".to_string();
} else if add_table_state.columns.is_empty() {
*command_message = "Cannot save: No columns defined.".to_string();
} else {
*command_message = "Saving table...".to_string();
app_state.show_loading_dialog("Saving", "Please wait...");
let mut client_clone = grpc_client.clone();
let state_clone = add_table_state.clone();
let sender_clone = save_result_sender.clone();
tokio::spawn(async move {
let result = handle_save_table_action(&mut client_clone, &state_clone).await;
let _ = sender_clone.send(result).await; // Send result back
});
}
// --- End Initiate Async Save ---
}
AddTableFocus::DeleteSelectedButton => {
// --- Show Confirmation Dialog ---

View File

@@ -40,6 +40,7 @@ use crate::config::binds::key_sequences::KeySequenceTracker;
use tokio::sync::mpsc;
use crate::tui::functions::common::login::LoginResult;
use crate::tui::functions::common::register::RegisterResult;
use crate::functions::modes::navigation::add_table_nav::SaveTableResultSender;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EventOutcome {
@@ -61,12 +62,14 @@ pub struct EventHandler {
pub auth_client: AuthClient,
pub login_result_sender: mpsc::Sender<LoginResult>,
pub register_result_sender: mpsc::Sender<RegisterResult>,
pub save_table_result_sender: SaveTableResultSender,
}
impl EventHandler {
pub async fn new(
login_result_sender: mpsc::Sender<LoginResult>,
register_result_sender: mpsc::Sender<RegisterResult>,
save_table_result_sender: SaveTableResultSender,
) -> Result<Self> {
Ok(EventHandler {
command_mode: false,
@@ -80,6 +83,7 @@ impl EventHandler {
auth_client: AuthClient::new().await?,
login_result_sender,
register_result_sender,
save_table_result_sender,
})
}
@@ -189,11 +193,16 @@ impl EventHandler {
}
// --- Add Table Page Navigation ---
if app_state.ui.show_add_table {
let client_clone = grpc_client.clone();
let sender_clone = self.save_table_result_sender.clone();
if add_table_nav::handle_add_table_navigation(
key,
config,
app_state,
&mut admin_state.add_table_state,
client_clone,
sender_clone,
&mut self.command_message,
) {

View File

@@ -8,7 +8,7 @@ use common::proto::multieko2::table_structure::table_structure_service_client::T
use common::proto::multieko2::table_structure::TableStructureResponse;
use common::proto::multieko2::table_definition::{
table_definition_client::TableDefinitionClient,
ProfileTreeResponse
ProfileTreeResponse, PostTableDefinitionRequest, TableDefinitionResponse,
};
use anyhow::Result;
@@ -67,4 +67,10 @@ impl GrpcClient {
let response = self.table_definition_client.get_profile_tree(request).await?;
Ok(response.into_inner())
}
pub async fn post_table_definition(&mut self, request: PostTableDefinitionRequest) -> Result<TableDefinitionResponse> {
let tonic_request = tonic::Request::new(request);
let response = self.table_definition_client.post_table_definition(tonic_request).await?;
Ok(response.into_inner())
}
}

View File

@@ -1,6 +1,13 @@
// src/tui/functions/common/add_table.rs
use crate::state::pages::add_table::{
AddTableFocus, AddTableState, ColumnDefinition, IndexDefinition,
AddTableFocus, AddTableState, ColumnDefinition, IndexDefinition, LinkDefinition,
};
use crate::services::GrpcClient;
use anyhow::{anyhow, Result};
use common::proto::multieko2::table_definition::{
PostTableDefinitionRequest,
ColumnDefinition as ProtoColumnDefinition,
TableLink as ProtoTableLink,
};
/// Handles the logic for adding a column when the "Add" button is activated.
@@ -113,3 +120,76 @@ pub fn handle_delete_selected_columns(
}
}
/// Prepares and sends the request to save the new table definition via gRPC.
pub async fn handle_save_table_action(
grpc_client: &mut GrpcClient,
add_table_state: &AddTableState,
) -> Result<String> {
// --- Basic Validation ---
if add_table_state.table_name.is_empty() {
return Err(anyhow!("Table name cannot be empty."));
}
if add_table_state.columns.is_empty() {
return Err(anyhow!("Table must have at least one column."));
}
// --- Prepare Proto Data ---
let proto_columns: Vec<ProtoColumnDefinition> = add_table_state
.columns
.iter()
.map(|col| ProtoColumnDefinition {
name: col.name.clone(),
field_type: col.data_type.clone(), // Assuming data_type maps directly
})
.collect();
let proto_indexes: Vec<String> = add_table_state
.indexes
.iter()
.filter(|idx| idx.selected) // Only include selected indexes
.map(|idx| idx.name.clone())
.collect();
let proto_links: Vec<ProtoTableLink> = add_table_state
.links
.iter()
.filter(|link| link.selected) // Only include selected links
.map(|link| ProtoTableLink {
linked_table_name: link.linked_table_name.clone(),
// Assuming 'required' maps directly, adjust if needed
// For now, the proto only seems to use linked_table_name based on example
// If your proto evolves, map link.is_required here.
required: false, // Set based on your proto definition/needs
})
.collect();
// --- Create Request ---
let request = PostTableDefinitionRequest {
table_name: add_table_state.table_name.clone(),
columns: proto_columns,
indexes: proto_indexes,
links: proto_links,
profile_name: add_table_state.profile_name.clone(),
};
// --- Call gRPC Service ---
match grpc_client.post_table_definition(request).await {
Ok(response) => {
if response.success {
Ok(format!(
"Table '{}' saved successfully.",
add_table_state.table_name
))
} else {
// Use the SQL message from the response if available, otherwise generic error
let error_message = if !response.sql.is_empty() {
format!("Server failed to save table: {}", response.sql)
} else {
"Server failed to save table (unknown reason).".to_string()
};
Err(anyhow!(error_message))
}
}
Err(e) => Err(anyhow!("gRPC call failed: {}", e)),
}
}

View File

@@ -21,6 +21,8 @@ use crate::tui::terminal::{EventReader, TerminalCore};
use crate::ui::handlers::render::render_ui;
use crate::tui::functions::common::login::LoginResult;
use crate::tui::functions::common::register::RegisterResult;
use crate::tui::functions::common::add_table::handle_save_table_action;
use crate::functions::modes::navigation::add_table_nav::SaveTableResultSender;
use crate::tui::functions::common::login;
use crate::tui::functions::common::register;
use std::time::Instant;
@@ -42,9 +44,13 @@ pub async fn run_ui() -> Result<()> {
mpsc::channel::<LoginResult>(1);
let (register_result_sender, mut register_result_receiver) =
mpsc::channel::<RegisterResult>(1);
let (save_table_result_sender, mut save_table_result_receiver) =
mpsc::channel::<Result<String>>(1);
let mut event_handler = EventHandler::new(
login_result_sender.clone(),
register_result_sender.clone(),
save_table_result_sender.clone(),
).await.context("Failed to create event handler")?;
let event_reader = EventReader::new();
@@ -215,6 +221,31 @@ pub async fn run_ui() -> Result<()> {
error!("Register result channel disconnected unexpectedly.");
}
}
// --- Check for Save Table Results ---
match save_table_result_receiver.try_recv() {
Ok(result) => {
app_state.hide_dialog(); // Hide loading indicator
match result {
Ok(success_message) => {
event_handler.command_message = success_message;
admin_state.add_table_state.has_unsaved_changes = false;
// Optionally refresh profile tree if needed
// let _ = UiService::initialize_app_state(&mut grpc_client, &mut app_state).await;
// Navigate back to Admin view
buffer_state.update_history(AppView::Admin);
}
Err(e) => {
event_handler.command_message = format!("Save failed: {}", e);
// Optionally show an error dialog instead of just command message
}
}
needs_redraw = true;
}
Err(mpsc::error::TryRecvError::Empty) => {} // No message
Err(mpsc::error::TryRecvError::Disconnected) => {
error!("Save table result channel disconnected unexpectedly.");
}
}
// --- Centralized Consequence Handling ---
let mut should_exit = false;