hidden from the user now in the form
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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") {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
14
client/src/utils/columns.rs
Normal file
14
client/src/utils/columns.rs
Normal 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
4
client/src/utils/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// src/utils/mod.rs
|
||||||
|
|
||||||
|
pub mod columns;
|
||||||
|
pub use columns::*;
|
||||||
Reference in New Issue
Block a user