-
Notifications
You must be signed in to change notification settings - Fork 0
Description
ISSUE-067: UI Configuration Editor
Description
Currently, users must manually edit the config.yaml file to customize application settings. This issue proposes implementing a user-friendly dialog interface that allows users to modify configuration settings directly from the application UI.
Current State
- Configuration is stored in
config.yaml(auto-generated on first run) - Users must edit YAML file manually with a text editor
- No GUI way to modify settings
- Risk of syntax errors when editing YAML manually
- Settings available:
- alerts: warning_days, critical_days
- lock: timeout_minutes, heartbeat_interval_seconds
- organization: roles list, workspaces list
Problem
User Experience Issues:
- Non-technical users may be uncomfortable editing YAML files
- Risk of breaking syntax (indentation, format errors)
- No visual feedback on valid value ranges
- No validation until application restart
- Changes require manual file editing with external tools
Support Issues:
- Users need to understand YAML syntax
- Configuration errors cause application failures
- Hard to troubleshoot user config mistakes
- Documentation must explain YAML editing
Expected Behavior
Main Dialog Features
Access:
- New "⚙️ Paramètres" button in main navigation bar
- Opens modal dialog similar to "Alert Settings" dialog
Tabbed Interface (3 tabs):
Tab 1: ⚠️ Alertes (Alerts)
┌─────────────────────────────────────────────┐
│ ⚠️ Paramètres d'Alerte │
│ │
│ Jours Warning : [30 ] │
│ Jours Critique: [7 ] │
│ │
│ Validation: critical < warning │
└─────────────────────────────────────────────┘
Tab 2: 🔒 Verrouillage (Lock)
┌─────────────────────────────────────────────┐
│ 🔒 Verrouillage Concurrent │
│ │
│ Timeout (minutes): [2 ] │
│ Heartbeat (secondes): [30 ] │
│ │
│ Prevents multiple users from editing │
└─────────────────────────────────────────────┘
Tab 3: 🏢 Organisation
┌─────────────────────────────────────────────┐
│ 🏢 Structure Organisation │
│ │
│ Postes/Rôles : │
│ ┌──────────────────────────────────────┐ │
│ │ Cariste [X] │ │
│ │ Préparateur de commandes [X] │ │
│ │ Magasinier [X] │ │
│ │ [+ Ajouter] │ │
│ └──────────────────────────────────────┘ │
│ │
│ Zones de travail : │
│ ┌──────────────────────────────────────┐ │
│ │ Quai [X] │ │
│ │ Zone A [X] │ │
│ │ [+ Ajouter] │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
Dialog Behavior
Similar to AlertSettingsDialog:
- Modal window (blocks main app)
- 3 buttons: Enregistrer, Réinitialiser, Annuler
- Validation before save
- Unsaved changes detection (via BaseFormDialog)
- Confirmation prompt if closing with unsaved changes
- Status messages (success/error)
- Auto-close after successful save (1 second delay)
Validation:
- Positive values for all numeric fields
critical_days < warning_days- At least 1 role in organization
- At least 1 workspace in organization
- No empty strings in lists
Implementation Details
Files to Create
-
src/ui_ctk/dialogs/app_config_dialog.py(NEW)AppConfigDialogclass- Extends
BaseFormDialog - 300-400 lines estimated
- Pattern: Similar to
AlertSettingsDialog - Uses
CTkNotebookfor tabs
-
src/utils/config_validators.py(OPTIONAL)- Specific validators for UI config editing
- May reuse existing
validate_config() - Helper functions for real-time validation
Files to Modify
-
src/ui_ctk/main_window.py- Add
show_app_settings()method - Add "⚙️ Paramètres" button to navigation bar
- Integrate with existing navigation pattern
- Add
-
src/ui_ctk/constants.py(OPTIONAL)- May add
NAV_SETTINGS = "Paramètres"constant
- May add
Key Methods to Implement
class AppConfigDialog(BaseFormDialog):
def __init__(self, parent):
# Load current config with load_config()
# Store original for unsaved changes detection
# Initialize Tkinter variables for each field
def create_form(self):
# Create CTkNotebook with 3 tabs
# Call _create_alerts_tab(), _create_lock_tab(), _create_org_tab()
def _create_alerts_tab(self, parent):
# 2 numeric inputs: warning_days, critical_days
# Validation labels
def _create_lock_tab(self, parent):
# 2 numeric inputs: timeout_minutes, heartbeat_interval_seconds
# Help text explaining concurrent access
def _create_organization_tab(self, parent):
# 2 editable lists with add/remove buttons
# Scrollable frames for each list
# Pattern: Similar to employee detail list views
def _add_item(self, container, vars_list):
# Add new row with entry + delete button
def _remove_item(self, row, var, vars_list):
# Remove row from list
def validate(self) -> Tuple[bool, Optional[str]]:
# Validate all fields
# Check critical_days < warning_days
# Check list not empty
# Check positive values
def save(self):
# Build config dict from Tkinter variables
# Call validate_config() for final check
# Call save_config() to write config.yaml
# Set result = TrueIntegration with Existing Config System
Reuse existing functions:
from utils.config import load_config, save_config, validate_config
# Load current configuration
config = load_config()
# Save modified configuration
save_config(new_config, Path("config.yaml"))
# Validate before saving
is_valid, errors = validate_config(new_config)Editable Lists Implementation Pattern
For roles and workspaces lists:
def _create_editable_list(self, parent, items: list[str], title: str):
"""
Create an editable list with add/remove buttons.
Returns:
List of StringVar for data binding
"""
vars_list = []
container = ctk.CTkFrame(parent)
container.pack(fill="both", expand=True)
# Title label
ctk.CTkLabel(container, text=title, font=("Arial", 12, "bold")).pack(anchor="w")
# Scrollable list
scroll = ctk.CTkScrollableFrame(container, height=150)
scroll.pack(fill="both", expand=True)
# Create row for each item
for item in items:
row = ctk.CTkFrame(scroll, fg_color="transparent")
row.pack(fill="x", pady=2)
var = ctk.StringVar(value=item)
vars_list.append(var)
ctk.CTkEntry(row, textvariable=var).pack(side="left", fill="x", expand=True)
ctk.CTkButton(
row, text="✕", width=30,
command=lambda: self._remove_item(row, var, vars_list)
).pack(side="left")
# Add button
ctk.CTkButton(
container, text="+ Ajouter",
command=lambda: self._add_item(scroll, vars_list)
).pack(anchor="w")
return vars_listUI/UX Considerations
Dialog Size & Position
- Size: 900x750 (larger than AlertSettingsDialog)
- Centered on parent window
- Modal (blocks main app)
Visual Feedback
- Color-coded validation indicators (similar to AlertSettingsDialog)
- Real-time validation where possible
- Clear error messages
- Success message with auto-close
Unsaved Changes
- Leverage
BaseFormDialogautomatic tracking - Warning on close if unsaved
- Options: Save, Discard, Cancel
Accessibility
- Clear labels in French
- Helpful tooltips/help text
- Logical tab ordering
- Keyboard navigation support
Technical Challenges
1. YAML Comment Preservation
Issue: PyYAML loses comments when saving
Solutions (in preference order):
- Accept comment loss - Regenerate template with new values
- Use ruamel.yaml - Preserves comments (new dependency)
- Hybrid approach - Save values only, users re-edit in text editor if needed
Recommendation: Accept comment loss (option 1)
- Template comments are for first-time setup
- Power users can still edit YAML manually
- Simpler implementation, no new dependencies
2. Real-time Validation
Approach: Use trace_add on Tkinter variables
# Validate when value changes
self.warning_days_var.trace_add('write', self._on_warning_days_changed)
def _on_warning_days_changed(self, *args):
warning = self.warning_days_var.get()
critical = self.critical_days_var.get()
if warning <= critical:
# Show validation error
self.warning_error_label.configure(
text="Doit être supérieur à critique",
text_color="red"
)
self.warning_entry.configure(border_color="red")
else:
# Clear error
self.warning_error_label.configure(text="")
self.warning_entry.configure(border_color="gray")3. Config Reload After Save
Issue: Application needs to use new values
Solutions:
- Hot reload - Reload config and update all components
- Restart required - Prompt user to restart app
- Selective reload - Reload only affected modules
Recommendation: Restart required (simplest)
- Show dialog: "Configuration sauvegardée. Veuillez redémarrer l'application."
- Consistent behavior, no complex state management
Affected Files
New Files
src/ui_ctk/dialogs/app_config_dialog.py- Main dialog implementation
Modified Files
src/ui_ctk/main_window.py- Add settings button and callbacksrc/ui_ctk/constants.py- Optionally add NAV_SETTINGS constant
Optional Files
src/utils/config_validators.py- UI-specific validators (if needed)
Implementation Plan
-
Phase 1: Basic Dialog Structure
- Create AppConfigDialog class extending BaseFormDialog
- Implement dialog layout with CTkNotebook (3 tabs)
- Add buttons (Enregistrer, Réinitialiser, Annuler)
- Wire up unsaved changes detection
-
Phase 2: Alerts & Lock Tabs
- Implement alerts tab with 2 numeric inputs
- Implement lock tab with 2 numeric inputs
- Add validation (positive values, critical < warning)
- Test save/load functionality
-
Phase 3: Organization Tab
- Implement editable lists for roles
- Implement editable lists for workspaces
- Add add/remove functionality
- Validate non-empty lists
-
Phase 4: Integration
- Add settings button to MainWindow
- Implement show_app_settings() callback
- Add restart prompt after save
- End-to-end testing
-
Phase 5: Polish
- Add help text/tooltips
- Improve visual feedback
- Add keyboard shortcuts
- Accessibility review
- Documentation updates
Acceptance Criteria
- "⚙️ Paramètres" button visible in main navigation
- Dialog opens with current config values loaded
- All 3 tabs display correctly with appropriate fields
- Can modify alerts settings and save successfully
- Can modify lock settings and save successfully
- Can add/edit/remove roles in organization tab
- Can add/edit/remove workspaces in organization tab
- Validation prevents invalid saves
- Unsaved changes prompt appears when closing
- Reset button restores values from config file
- Cancel button closes without saving
- Save button writes valid config.yaml file
- App prompts for restart after saving
- New settings are loaded after restart
- All existing tests pass
- New tests for dialog functionality
Estimated Effort
Total: 6-8 hours
- Phase 1 (Dialog structure): 1.5 hours
- Phase 2 (Alerts & Lock tabs): 2 hours
- Phase 3 (Organization tab with lists): 2.5 hours
- Phase 4 (Integration): 1 hour
- Phase 5 (Polish & testing): 1-1.5 hours
Related Issues
None
Dependencies
- BLOCKED BY: None
- BLOCKS: None
- RELATED: None
Example Use Cases
Use Case 1: Adjust Alert Thresholds
- Warehouse manager wants earlier warnings for certifications
- Opens ⚙️ Paramètres dialog
- Goes to "
⚠️ Alertes" tab - Changes "Jours Warning" from 30 to 60
- Clicks "Enregistrer"
- Dialog closes, prompt to restart appears
- After restart, warnings now appear 60 days before expiration
Use Case 2: Add New Workspace
- Company opens new warehouse zone "Zone D"
- Opens ⚙️ Paramètres dialog
- Goes to "🏢 Organisation" tab
- In "Zones de travail" list, clicks "+ Ajouter"
- Types "Zone D" in new entry
- Clicks "Enregistrer"
- After restart, "Zone D" appears in workspace dropdowns
Use Case 3: Configure Concurrent Access
- IT wants to adjust lock timeout for slow network
- Opens ⚙️ Paramètres dialog
- Goes to "🔒 Verrouillage" tab
- Changes "Timeout (minutes)" from 2 to 5
- Clicks "Enregistrer"
- After restart, lock timeout is now 5 minutes
Notes
Design Patterns to Follow
- AlertSettingsDialog: Good reference for tabbed config dialog
- BaseFormDialog: Extend for unsaved changes tracking
- employee_detail.py: Reference for editable list patterns
Configuration System
- Config file location:
config.yamlin working directory - File format: YAML (with JSON fallback)
- Auto-generated on first run
- Uses PyYAML library
- Comments may be lost on save (acceptable)
Future Enhancements
- GUI-based config editor for advanced settings (database path, log level)
- Import/export of configuration files
- Configuration presets (templates for different warehouse types)
- Per-user configuration profiles
- Real-time config reload (without restart)
Documentation Updates Required
- User manual: "Configuration" section
- Screenshot of config dialog
- Explanation of each setting
- Troubleshooting common config issues