admin_panel for admins have now some adjustements
This commit is contained in:
@@ -82,8 +82,8 @@ pub fn render_admin_panel_admin(
|
|||||||
|
|
||||||
// Build and render profile list inside the block's inner area
|
// Build and render profile list inside the block's inner area
|
||||||
let profile_list = List::new(profile_list_items)
|
let profile_list = List::new(profile_list_items)
|
||||||
// Highlight style depends on focus AND navigation state
|
// Highlight style depends only on Profiles focus
|
||||||
.highlight_style(if profile_focus { // Use focus state
|
.highlight_style(if profile_focus {
|
||||||
Style::default().add_modifier(ratatui::style::Modifier::REVERSED)
|
Style::default().add_modifier(ratatui::style::Modifier::REVERSED)
|
||||||
} else {
|
} else {
|
||||||
Style::default()
|
Style::default()
|
||||||
@@ -93,8 +93,8 @@ pub fn render_admin_panel_admin(
|
|||||||
f.render_stateful_widget(profile_list, profiles_inner_area, &mut admin_state.profile_list_state);
|
f.render_stateful_widget(profile_list, profiles_inner_area, &mut admin_state.profile_list_state);
|
||||||
|
|
||||||
// --- Tables Pane (Middle) ---
|
// --- Tables Pane (Middle) ---
|
||||||
let table_focus = admin_state.current_focus == AdminFocus::Tables;
|
let table_pane_has_focus = matches!(admin_state.current_focus, AdminFocus::Tables | AdminFocus::InsideTablesList);
|
||||||
let table_border_style = if table_focus {
|
let table_border_style = if table_pane_has_focus {
|
||||||
Style::default().fg(theme.highlight)
|
Style::default().fg(theme.highlight)
|
||||||
} else {
|
} else {
|
||||||
Style::default().fg(theme.border)
|
Style::default().fg(theme.border)
|
||||||
@@ -157,13 +157,13 @@ pub fn render_admin_panel_admin(
|
|||||||
|
|
||||||
// Build and render table list inside the block's inner area
|
// Build and render table list inside the block's inner area
|
||||||
let table_list = List::new(table_list_items)
|
let table_list = List::new(table_list_items)
|
||||||
// Highlight style depends on focus AND navigation state
|
// Highlight style depends on whether the pane OR inside has focus
|
||||||
.highlight_style(if table_focus { // Use focus state
|
.highlight_style(if table_pane_has_focus {
|
||||||
Style::default().add_modifier(ratatui::style::Modifier::REVERSED)
|
Style::default().add_modifier(ratatui::style::Modifier::REVERSED)
|
||||||
} else {
|
} else {
|
||||||
Style::default()
|
Style::default()
|
||||||
})
|
})
|
||||||
.highlight_symbol(if table_focus { "> " } else { " " }); // Focus indicator
|
.highlight_symbol("> ");
|
||||||
|
|
||||||
f.render_stateful_widget(table_list, tables_inner_area, &mut admin_state.table_list_state);
|
f.render_stateful_widget(table_list, tables_inner_area, &mut admin_state.table_list_state);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,37 @@ use crossterm::event::KeyEvent;
|
|||||||
use crate::state::app::buffer::AppView;
|
use crate::state::app::buffer::AppView;
|
||||||
use crate::state::app::buffer::BufferState;
|
use crate::state::app::buffer::BufferState;
|
||||||
use crate::state::pages::add_table::{AddTableState, LinkDefinition};
|
use crate::state::pages::add_table::{AddTableState, LinkDefinition};
|
||||||
|
use ratatui::widgets::ListState;
|
||||||
|
|
||||||
|
// --- Helper functions for ListState navigation (similar to TableState) ---
|
||||||
|
fn list_select_next(list_state: &mut ListState, item_count: usize) {
|
||||||
|
if item_count == 0 {
|
||||||
|
list_state.select(None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let i = match list_state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i >= item_count - 1 { 0 } else { i + 1 }
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
list_state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_select_previous(list_state: &mut ListState, item_count: usize) {
|
||||||
|
if item_count == 0 {
|
||||||
|
list_state.select(None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let i = match list_state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i == 0 { item_count - 1 } else { i - 1 }
|
||||||
|
}
|
||||||
|
None => item_count - 1, // Select last if nothing was selected
|
||||||
|
};
|
||||||
|
list_state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Handles navigation events specifically for the Admin Panel view.
|
/// Handles navigation events specifically for the Admin Panel view.
|
||||||
/// Returns true if the event was handled, false otherwise.
|
/// Returns true if the event was handled, false otherwise.
|
||||||
@@ -20,36 +51,45 @@ pub fn handle_admin_navigation(
|
|||||||
buffer_state: &mut BufferState,
|
buffer_state: &mut BufferState,
|
||||||
command_message: &mut String,
|
command_message: &mut String,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let action = config.get_general_action(key.code, key.modifiers);
|
let action = config.get_general_action(key.code, key.modifiers).map(String::from); // Clone action string
|
||||||
let current_focus = admin_state.current_focus;
|
let current_focus = admin_state.current_focus;
|
||||||
let profile_count = app_state.profile_tree.profiles.len();
|
let profile_count = app_state.profile_tree.profiles.len();
|
||||||
|
let mut new_focus = current_focus; // Start with current focus
|
||||||
|
let mut handled = true; // Assume handled unless logic says otherwise
|
||||||
|
|
||||||
match action {
|
match action.as_deref() {
|
||||||
// --- Vertical Navigation (Up/Down) ---
|
// --- Vertical Navigation (Up/Down) ---
|
||||||
Some("move_up") => {
|
Some("move_up") => {
|
||||||
match current_focus {
|
match current_focus {
|
||||||
AdminFocus::Profiles => {
|
AdminFocus::Profiles => {
|
||||||
if profile_count > 0 {
|
if profile_count > 0 {
|
||||||
// Updates navigation state, resets table state
|
|
||||||
admin_state.previous_profile(profile_count);
|
admin_state.previous_profile(profile_count);
|
||||||
*command_message = "Navigated profiles".to_string();
|
*command_message = "Navigated profiles list".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AdminFocus::Tables => {
|
AdminFocus::Tables => { // Navigate highlight when focus is on the block
|
||||||
// Updates table navigation state
|
// Updates table navigation state
|
||||||
if let Some(nav_profile_idx) = admin_state.profile_list_state.selected() {
|
if let Some(nav_profile_idx) = admin_state.profile_list_state.selected() {
|
||||||
if let Some(profile) = app_state.profile_tree.profiles.get(nav_profile_idx) {
|
if let Some(profile) = app_state.profile_tree.profiles.get(nav_profile_idx) {
|
||||||
let table_count = profile.tables.len();
|
let table_count = profile.tables.len();
|
||||||
if table_count > 0 {
|
if table_count > 0 {
|
||||||
admin_state.previous_table(table_count);
|
admin_state.previous_table(table_count);
|
||||||
*command_message = "Navigated tables".to_string();
|
*command_message = "Navigated tables list".to_string();
|
||||||
|
} else {
|
||||||
|
*command_message = "No tables in selected profile".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AdminFocus::InsideTablesList => { // Scroll inside
|
||||||
|
if let Some(p_idx) = admin_state.profile_list_state.selected().or(admin_state.selected_profile_index) { // Use nav or persistent selection
|
||||||
|
if let Some(profile) = app_state.profile_tree.profiles.get(p_idx) {
|
||||||
|
list_select_previous(&mut admin_state.table_list_state, profile.tables.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
AdminFocus::Button1 | AdminFocus::Button2 | AdminFocus::Button3 => {}
|
AdminFocus::Button1 | AdminFocus::Button2 | AdminFocus::Button3 => {}
|
||||||
}
|
}
|
||||||
true // Event handled
|
|
||||||
}
|
}
|
||||||
Some("move_down") => {
|
Some("move_down") => {
|
||||||
match current_focus {
|
match current_focus {
|
||||||
@@ -57,29 +97,36 @@ pub fn handle_admin_navigation(
|
|||||||
if profile_count > 0 {
|
if profile_count > 0 {
|
||||||
// Updates navigation state, resets table state
|
// Updates navigation state, resets table state
|
||||||
admin_state.next_profile(profile_count);
|
admin_state.next_profile(profile_count);
|
||||||
*command_message = "Navigated profiles".to_string();
|
*command_message = "Navigated profiles list".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AdminFocus::Tables => {
|
AdminFocus::Tables => { // Navigate highlight when focus is on the block
|
||||||
if let Some(nav_profile_idx) = admin_state.profile_list_state.selected() {
|
if let Some(nav_profile_idx) = admin_state.profile_list_state.selected() {
|
||||||
if let Some(profile) = app_state.profile_tree.profiles.get(nav_profile_idx) {
|
if let Some(profile) = app_state.profile_tree.profiles.get(nav_profile_idx) {
|
||||||
let table_count = profile.tables.len();
|
let table_count = profile.tables.len();
|
||||||
if table_count > 0 {
|
if table_count > 0 {
|
||||||
admin_state.next_table(table_count);
|
admin_state.next_table(table_count);
|
||||||
*command_message = "Navigated tables".to_string();
|
*command_message = "Navigated tables list".to_string();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
*command_message = "No tables in selected profile".to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AdminFocus::InsideTablesList => { // Scroll inside
|
||||||
|
if let Some(p_idx) = admin_state.profile_list_state.selected().or(admin_state.selected_profile_index) { // Use nav or persistent selection
|
||||||
|
if let Some(profile) = app_state.profile_tree.profiles.get(p_idx) {
|
||||||
|
list_select_next(&mut admin_state.table_list_state, profile.tables.len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AdminFocus::Button1 | AdminFocus::Button2 | AdminFocus::Button3 => {}
|
AdminFocus::Button1 | AdminFocus::Button2 | AdminFocus::Button3 => {}
|
||||||
}
|
}
|
||||||
true // Event handled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Horizontal Navigation (Focus Change) ---
|
// --- Horizontal Navigation (Focus Change) ---
|
||||||
Some("next_option") | Some("previous_option") => {
|
Some("next_option") | Some("previous_option") => {
|
||||||
let old_focus = admin_state.current_focus;
|
let old_focus = admin_state.current_focus;
|
||||||
let is_next = action == Some("next_option"); // Check if 'l' or 'h'
|
let is_next = action.as_deref() == Some("next_option");
|
||||||
|
|
||||||
admin_state.current_focus = match old_focus {
|
admin_state.current_focus = match old_focus {
|
||||||
AdminFocus::Profiles => if is_next { AdminFocus::Tables } else { AdminFocus::Button3 }, // P -> T (l) or P -> B3 (h)
|
AdminFocus::Profiles => if is_next { AdminFocus::Tables } else { AdminFocus::Button3 }, // P -> T (l) or P -> B3 (h)
|
||||||
@@ -87,6 +134,8 @@ pub fn handle_admin_navigation(
|
|||||||
AdminFocus::Button1 => if is_next { AdminFocus::Button2 } else { AdminFocus::Tables }, // B1 -> B2 (l) or B1 -> T (h)
|
AdminFocus::Button1 => if is_next { AdminFocus::Button2 } else { AdminFocus::Tables }, // B1 -> B2 (l) or B1 -> T (h)
|
||||||
AdminFocus::Button2 => if is_next { AdminFocus::Button3 } else { AdminFocus::Button1 }, // B2 -> B3 (l) or B2 -> B1 (h)
|
AdminFocus::Button2 => if is_next { AdminFocus::Button3 } else { AdminFocus::Button1 }, // B2 -> B3 (l) or B2 -> B1 (h)
|
||||||
AdminFocus::Button3 => if is_next { AdminFocus::Profiles } else { AdminFocus::Button2 }, // B3 -> P (l) or B3 -> B2 (h)
|
AdminFocus::Button3 => if is_next { AdminFocus::Profiles } else { AdminFocus::Button2 }, // B3 -> P (l) or B3 -> B2 (h)
|
||||||
|
// Prevent horizontal nav when inside lists
|
||||||
|
AdminFocus::InsideTablesList => old_focus,
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_focus = admin_state.current_focus;
|
let new_focus = admin_state.current_focus;
|
||||||
@@ -117,45 +166,63 @@ pub fn handle_admin_navigation(
|
|||||||
// admin_state.profile_list_state.select(None); // Optional: clear profile nav highlight
|
// admin_state.profile_list_state.select(None); // Optional: clear profile nav highlight
|
||||||
}
|
}
|
||||||
|
|
||||||
true // Event handled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Selection ---
|
// --- Selection ---
|
||||||
Some("select") => {
|
Some("select") => {
|
||||||
match current_focus {
|
match current_focus {
|
||||||
AdminFocus::Profiles => {
|
AdminFocus::Profiles => {
|
||||||
|
// --- Perform persistent selection ---
|
||||||
// Set the persistent selection to the currently navigated item
|
// Set the persistent selection to the currently navigated item
|
||||||
if let Some(nav_idx) = admin_state.profile_list_state.selected() {
|
if let Some(nav_idx) = admin_state.profile_list_state.selected() {
|
||||||
admin_state.selected_profile_index = Some(nav_idx); // Set persistent selection
|
admin_state.selected_profile_index = Some(nav_idx);
|
||||||
|
|
||||||
// Move focus to Tables (like pressing 'l')
|
// Move focus to Tables (like pressing 'l')
|
||||||
admin_state.current_focus = AdminFocus::Tables;
|
new_focus = AdminFocus::Tables;
|
||||||
|
|
||||||
// Select the first table for navigation highlight
|
// Select the first table for navigation highlight
|
||||||
admin_state.table_list_state.select(None); // Clear table nav first
|
admin_state.table_list_state.select(None); // Clear table nav first
|
||||||
admin_state.selected_table_index = None; // Clear persistent table selection
|
admin_state.selected_table_index = None; // Clear persistent table selection
|
||||||
if let Some(profile) = app_state.profile_tree.profiles.get(nav_idx) {
|
if let Some(profile) = app_state.profile_tree.profiles.get(nav_idx) {
|
||||||
if !profile.tables.is_empty() {
|
if !profile.tables.is_empty() {
|
||||||
// Set table nav highlight
|
admin_state.table_list_state.select(Some(0));
|
||||||
admin_state.table_list_state.select(Some(0));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*command_message = format!("Selected profile idx {}, focus on Tables", nav_idx);
|
*command_message = format!("Selected profile: {}", app_state.profile_tree.profiles[nav_idx].name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*command_message = "No profile selected".to_string();
|
*command_message = "No profile selected".to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AdminFocus::Tables => {
|
AdminFocus::Tables => {
|
||||||
|
// --- Enter InsideTablesList focus ---
|
||||||
|
new_focus = AdminFocus::InsideTablesList;
|
||||||
|
// Select first item if none selected when entering
|
||||||
|
if let Some(p_idx) = admin_state.profile_list_state.selected().or(admin_state.selected_profile_index) {
|
||||||
|
if let Some(profile) = app_state.profile_tree.profiles.get(p_idx) {
|
||||||
|
if admin_state.table_list_state.selected().is_none() && !profile.tables.is_empty() {
|
||||||
|
admin_state.table_list_state.select(Some(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*command_message = "Entered Tables List (Select item with Enter, Exit with Esc)".to_string();
|
||||||
|
}
|
||||||
|
AdminFocus::InsideTablesList => {
|
||||||
|
// --- Perform persistent selection ---
|
||||||
// Set the persistent selection to the currently navigated item
|
// Set the persistent selection to the currently navigated item
|
||||||
if let Some(nav_idx) = admin_state.table_list_state.selected() {
|
if let Some(nav_idx) = admin_state.table_list_state.selected() {
|
||||||
admin_state.selected_table_index = Some(nav_idx); // Set persistent selection
|
admin_state.selected_table_index = Some(nav_idx); // Set persistent selection
|
||||||
*command_message = format!("Selected table index {}", nav_idx);
|
// Get table name for message
|
||||||
|
let table_name = admin_state.profile_list_state.selected().or(admin_state.selected_profile_index)
|
||||||
|
.and_then(|p_idx| app_state.profile_tree.profiles.get(p_idx))
|
||||||
|
.and_then(|p| p.tables.get(nav_idx).map(|t| t.name.clone()))
|
||||||
|
.unwrap_or_else(|| "N/A".to_string());
|
||||||
|
*command_message = format!("Selected table: {}", table_name);
|
||||||
} else {
|
} else {
|
||||||
*command_message = "No table highlighted".to_string();
|
*command_message = "No table highlighted".to_string();
|
||||||
}
|
}
|
||||||
// We don't change focus here for now.
|
// Stay inside
|
||||||
}
|
}
|
||||||
|
|
||||||
AdminFocus::Button1 => {
|
AdminFocus::Button1 => {
|
||||||
*command_message = "Action: Add Logic (Not Implemented)".to_string();
|
*command_message = "Action: Add Logic (Not Implemented)".to_string();
|
||||||
// TODO: Trigger action for Button 1
|
// TODO: Trigger action for Button 1
|
||||||
@@ -165,24 +232,21 @@ pub fn handle_admin_navigation(
|
|||||||
if let Some(p_idx) = admin_state.selected_profile_index {
|
if let Some(p_idx) = admin_state.selected_profile_index {
|
||||||
if let Some(profile) = app_state.profile_tree.profiles.get(p_idx) {
|
if let Some(profile) = app_state.profile_tree.profiles.get(p_idx) {
|
||||||
let selected_profile_name = profile.name.clone();
|
let selected_profile_name = profile.name.clone();
|
||||||
// --- Populate Links from Profile Tables ---
|
// Populate links from the selected profile's tables
|
||||||
let available_links: Vec<LinkDefinition> = profile
|
let available_links: Vec<LinkDefinition> = profile
|
||||||
.tables
|
.tables
|
||||||
.iter()
|
.iter()
|
||||||
.map(|table| LinkDefinition {
|
.map(|table| LinkDefinition {
|
||||||
linked_table_name: table.name.clone(),
|
linked_table_name: table.name.clone(),
|
||||||
is_required: false,
|
is_required: false, // Default
|
||||||
selected: false,
|
selected: false, // Default
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
// --- End Populate Links ---
|
|
||||||
|
|
||||||
|
|
||||||
// Create and populate the new AddTableState
|
// Create and populate the new AddTableState
|
||||||
let new_add_table_state = AddTableState {
|
let new_add_table_state = AddTableState {
|
||||||
profile_name: selected_profile_name,
|
profile_name: selected_profile_name,
|
||||||
links: available_links,
|
links: available_links, // Assign populated links
|
||||||
// Reset other fields to defaults for a fresh start
|
|
||||||
..AddTableState::default()
|
..AddTableState::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,16 +274,37 @@ pub fn handle_admin_navigation(
|
|||||||
// TODO: Trigger action for Button 3
|
// TODO: Trigger action for Button 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true // Event handled
|
|
||||||
}
|
}
|
||||||
|
// --- Handle Exiting Inside Mode ---
|
||||||
|
Some("exit_table_scroll") => { // Assuming you have this action bound (e.g., to Esc)
|
||||||
|
match current_focus {
|
||||||
|
AdminFocus::InsideTablesList => {
|
||||||
|
new_focus = AdminFocus::Tables;
|
||||||
|
admin_state.table_list_state.select(None); // Clear nav highlight on exit
|
||||||
|
*command_message = "Exited Tables List".to_string();
|
||||||
|
}
|
||||||
|
_ => handled = false, // Not applicable
|
||||||
|
}
|
||||||
|
}
|
||||||
// --- Other General Keys (Ignore for admin nav) ---
|
// --- Other General Keys (Ignore for admin nav) ---
|
||||||
Some("toggle_sidebar") | Some("toggle_buffer_list") | Some("next_field") | Some("prev_field") => {
|
Some("toggle_sidebar") | Some("toggle_buffer_list") | Some("next_field") | Some("prev_field") => {
|
||||||
// These are handled globally or not applicable here.
|
// These are handled globally or not applicable here.
|
||||||
false
|
handled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- No matching action ---
|
// --- No matching action ---
|
||||||
_ => false, // Event not handled by admin navigation
|
_ => handled = false, // Event not handled by admin navigation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update focus state if it changed and was handled
|
||||||
|
if handled && current_focus != new_focus {
|
||||||
|
admin_state.current_focus = new_focus;
|
||||||
|
// Avoid overwriting specific messages set during 'select' or 'exit' handling
|
||||||
|
if command_message.is_empty() || command_message.starts_with("Focus set to") {
|
||||||
|
*command_message = format!("Focus set to {:?}", admin_state.current_focus);
|
||||||
|
}
|
||||||
|
} else if !handled {
|
||||||
|
// command_message.clear(); // Optional: Clear message if not handled here
|
||||||
|
}
|
||||||
|
|
||||||
|
handled // Return whether the event was handled by this function
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub enum AdminFocus {
|
|||||||
#[default] // Default focus is on the profiles list
|
#[default] // Default focus is on the profiles list
|
||||||
Profiles,
|
Profiles,
|
||||||
Tables,
|
Tables,
|
||||||
|
InsideTablesList,
|
||||||
Button1,
|
Button1,
|
||||||
Button2,
|
Button2,
|
||||||
Button3,
|
Button3,
|
||||||
|
|||||||
Reference in New Issue
Block a user