hidden from the user now in the form

This commit is contained in:
filipriec
2025-06-03 18:47:14 +02:00
parent 9540d9ccb9
commit 4ec569342d
7 changed files with 45 additions and 45 deletions

View File

@@ -7,6 +7,7 @@ pub mod components;
pub mod modes; pub mod modes;
pub mod functions; pub mod functions;
pub mod services; pub mod services;
pub mod utils;
pub use ui::run_ui; pub use ui::run_ui;

View File

@@ -5,6 +5,7 @@ use crate::state::pages::form::FormState;
use crate::tui::functions::common::form::SaveOutcome; use crate::tui::functions::common::form::SaveOutcome;
use crate::state::pages::add_logic::AddLogicState; use crate::state::pages::add_logic::AddLogicState;
use crate::state::app::state::AppState; use crate::state::app::state::AppState;
use crate::utils::columns::filter_user_columns;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
pub struct UiService; pub struct UiService;
@@ -82,7 +83,7 @@ impl UiService {
.into_iter() .into_iter()
.map(|col| col.name) .map(|col| col.name)
.collect(); .collect();
Ok(column_names) Ok(filter_user_columns(column_names))
} }
Err(e) => { Err(e) => {
tracing::warn!("Failed to fetch columns for {}.{}: {}", profile_name, table_name, e); tracing::warn!("Failed to fetch columns for {}.{}: {}", profile_name, table_name, e);
@@ -90,12 +91,10 @@ impl UiService {
} }
} }
} }
// MODIFIED: To set initial view table in AppState and return initial column names
pub async fn initialize_app_state_and_form( pub async fn initialize_app_state_and_form(
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
app_state: &mut AppState, app_state: &mut AppState,
// Returns (initial_profile, initial_table, initial_columns)
) -> Result<(String, String, Vec<String>)> { ) -> Result<(String, String, Vec<String>)> {
let profile_tree = grpc_client let profile_tree = grpc_client
.get_profile_tree() .get_profile_tree()
@@ -104,7 +103,6 @@ impl UiService {
app_state.profile_tree = profile_tree; app_state.profile_tree = profile_tree;
// Determine initial table to load (e.g., first table of first profile, or a default) // Determine initial table to load (e.g., first table of first profile, or a default)
// For now, let's hardcode a default for simplicity, but this should be more dynamic
let initial_profile_name = app_state let initial_profile_name = app_state
.profile_tree .profile_tree
.profiles .profiles
@@ -141,10 +139,11 @@ impl UiService {
.map(|col| col.name.clone()) .map(|col| col.name.clone())
.collect(); .collect();
Ok((initial_profile_name, initial_table_name, column_names)) let filtered_columns = filter_user_columns(column_names);
Ok((initial_profile_name, initial_table_name, filtered_columns))
} }
// NEW: Fetches and sets count for the current table in FormState
pub async fn fetch_and_set_table_count( pub async fn fetch_and_set_table_count(
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
form_state: &mut FormState, form_state: &mut FormState,
@@ -161,35 +160,26 @@ impl UiService {
))?; ))?;
form_state.total_count = total_count; form_state.total_count = total_count;
// Set initial position: if table has items, point to first, else point to new entry
if total_count > 0 { if total_count > 0 {
form_state.current_position = 1; form_state.current_position = 1;
} else { } else {
form_state.current_position = 1; // For a new entry in an empty table form_state.current_position = 1;
} }
Ok(()) Ok(())
} }
// MODIFIED: Generic table data loading
pub async fn load_table_data_by_position( pub async fn load_table_data_by_position(
grpc_client: &mut GrpcClient, grpc_client: &mut GrpcClient,
form_state: &mut FormState, // Takes &mut FormState to update it form_state: &mut FormState,
// position is now read from form_state.current_position
) -> Result<String> { ) -> Result<String> {
// Ensure current_position is valid before fetching
if form_state.current_position == 0 || (form_state.total_count > 0 && form_state.current_position > form_state.total_count) { if form_state.current_position == 0 || (form_state.total_count > 0 && form_state.current_position > form_state.total_count) {
// This indicates a "new entry" state, no data to load from server. form_state.reset_to_empty();
// The caller should handle this by calling form_state.reset_to_empty()
// or ensuring this function isn't called for a new entry position.
// For now, let's assume reset_to_empty was called if needed.
form_state.reset_to_empty(); // Ensure fields are clear for new entry
return Ok(format!( return Ok(format!(
"New entry mode for table {}.{}", "New entry mode for table {}.{}",
form_state.profile_name, form_state.table_name form_state.profile_name, form_state.table_name
)); ));
} }
if form_state.total_count == 0 && form_state.current_position == 1 { if form_state.total_count == 0 && form_state.current_position == 1 {
// Table is empty, this is the position for a new entry
form_state.reset_to_empty(); form_state.reset_to_empty();
return Ok(format!( return Ok(format!(
"New entry mode for empty table {}.{}", "New entry mode for empty table {}.{}",
@@ -197,7 +187,6 @@ impl UiService {
)); ));
} }
match grpc_client match grpc_client
.get_table_data_by_position( .get_table_data_by_position(
form_state.profile_name.clone(), form_state.profile_name.clone(),
@@ -208,7 +197,6 @@ impl UiService {
{ {
Ok(response) => { Ok(response) => {
form_state.update_from_response(&response.data); form_state.update_from_response(&response.data);
// ID, values, current_field, current_cursor_pos, has_unsaved_changes are set by update_from_response
Ok(format!( Ok(format!(
"Loaded entry {}/{} for table {}.{}", "Loaded entry {}/{} for table {}.{}",
form_state.current_position, form_state.current_position,
@@ -218,9 +206,6 @@ impl UiService {
)) ))
} }
Err(e) => { Err(e) => {
// If loading fails (e.g., record deleted, network error), what should happen?
// Maybe reset to a new entry state or show an error and keep current data.
// For now, log error and return error message.
tracing::error!( tracing::error!(
"Error loading entry {} for table {}.{}: {}", "Error loading entry {} for table {}.{}: {}",
form_state.current_position, form_state.current_position,
@@ -228,8 +213,6 @@ impl UiService {
form_state.table_name, form_state.table_name,
e e
); );
// Potentially clear form or revert to a safe state
// form_state.reset_to_empty();
Err(anyhow::anyhow!( Err(anyhow::anyhow!(
"Error loading entry {}: {}", "Error loading entry {}: {}",
form_state.current_position, form_state.current_position,
@@ -239,27 +222,20 @@ impl UiService {
} }
} }
// MODIFIED: To work with FormState's count and position
pub async fn handle_save_outcome( pub async fn handle_save_outcome(
save_outcome: SaveOutcome, save_outcome: SaveOutcome,
_grpc_client: &mut GrpcClient, // May not be needed if count is fetched separately _grpc_client: &mut GrpcClient,
_app_state: &mut AppState, // May not be needed directly _app_state: &mut AppState,
form_state: &mut FormState, form_state: &mut FormState,
) -> Result<()> { ) -> Result<()> {
match save_outcome { match save_outcome {
SaveOutcome::CreatedNew(new_id) => { SaveOutcome::CreatedNew(new_id) => {
// form_state.total_count and form_state.current_position should have been updated
// by the `save` function itself.
// Ensure form_state.id is set.
form_state.id = new_id; form_state.id = new_id;
// Potentially, re-fetch count to be absolutely sure, but save should be authoritative.
// UiService::fetch_and_set_table_count(grpc_client, form_state).await?;
} }
SaveOutcome::UpdatedExisting | SaveOutcome::NoChange => { SaveOutcome::UpdatedExisting | SaveOutcome::NoChange => {
// No changes to total_count or current_position needed from here. // No action needed
} }
} }
Ok(()) Ok(())
} }
} }

View File

@@ -107,11 +107,8 @@ impl FormState {
&mut self, &mut self,
response_data: &HashMap<String, String>, response_data: &HashMap<String, String>,
) { ) {
self.values = self.fields self.values = self.fields.iter()
.iter() .map(|field| response_data.get(field).cloned().unwrap_or_default())
.map(|field_name| {
response_data.get(field_name).cloned().unwrap_or_default()
})
.collect(); .collect();
if let Some(id_str) = response_data.get("id") { if let Some(id_str) = response_data.get("id") {

View File

@@ -21,9 +21,7 @@ pub async fn save(
return Ok(SaveOutcome::NoChange); return Ok(SaveOutcome::NoChange);
} }
let data_map: HashMap<String, String> = form_state let data_map: HashMap<String, String> = form_state.fields.iter()
.fields
.iter()
.zip(form_state.values.iter()) .zip(form_state.values.iter())
.map(|(field, value)| (field.clone(), value.clone())) .map(|(field, value)| (field.clone(), value.clone()))
.collect(); .collect();

View File

@@ -26,6 +26,7 @@ use crate::tui::functions::common::register::RegisterResult;
use crate::ui::handlers::context::DialogPurpose; use crate::ui::handlers::context::DialogPurpose;
use crate::tui::functions::common::login; use crate::tui::functions::common::login;
use crate::tui::functions::common::register; use crate::tui::functions::common::register;
use crate::utils::columns::filter_user_columns;
use std::time::Instant; use std::time::Instant;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use crossterm::cursor::SetCursorStyle; use crossterm::cursor::SetCursorStyle;
@@ -87,10 +88,19 @@ pub async fn run_ui() -> Result<()> {
.await .await
.context("Failed to initialize app state and form")?; .context("Failed to initialize app state and form")?;
// Initialize AppState and FormState with table data
let (initial_profile, initial_table, initial_columns_from_service) = // Renamed for clarity
UiService::initialize_app_state_and_form(&mut grpc_client, &mut app_state)
.await
.context("Failed to initialize app state and form")?;
// Filter the columns obtained from the service
let filtered_columns = filter_user_columns(initial_columns_from_service); // Use the correct variable
let mut form_state = FormState::new( let mut form_state = FormState::new(
initial_profile.clone(), initial_profile.clone(),
initial_table.clone(), initial_table.clone(),
initial_columns, filtered_columns,
); );
UiService::fetch_and_set_table_count(&mut grpc_client, &mut form_state) UiService::fetch_and_set_table_count(&mut grpc_client, &mut form_state)

View File

@@ -0,0 +1,14 @@
// src/utils/columns.rs
pub fn is_system_column(column_name: &str) -> bool {
match column_name {
"id" | "deleted" | "created_at" => true,
name if name.ends_with("_id") => true,
_ => false,
}
}
pub fn filter_user_columns(all_columns: Vec<String>) -> Vec<String> {
all_columns.into_iter()
.filter(|col| !is_system_column(col))
.collect()
}

4
client/src/utils/mod.rs Normal file
View File

@@ -0,0 +1,4 @@
// src/utils/mod.rs
pub mod columns;
pub use columns::*;