fix: 409 responses now swap and event log filtering works

- Add 409 to HTMX responseHandling config so selection conflict
  dialogs are displayed instead of silently ignored
- Fix event type dropdown using value="" which caused browsers to
  send display text "All types" instead of empty string
- Use value="all" for "All types" option (matching location selector)
- Handle event_type="all" in route as no filter
- Remove dead code (location_name lookup duplicated in template)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-02 12:16:56 +00:00
parent 0125bc4aaa
commit cccd76a44c
3 changed files with 10 additions and 14 deletions

View File

@@ -126,11 +126,13 @@ def create_app(
# So static_path should be the parent of static_base
static_path_for_fasthtml = str(static_base.parent) if static_base.exists() else "."
# Configure HTMX to swap 422 responses for validation errors
# Configure HTMX to swap certain error responses so UI feedback is visible
# 409 (Conflict) returns confirmation dialogs for selection mismatches
# 422 (Validation Error) returns forms with error messages
# Without this, hx-boost ignores non-2xx responses and errors appear to do nothing
htmx_config = Meta(
name="htmx-config",
content='{"responseHandling":[{"code":"204","swap":false},{"code":"[23]..","swap":true},{"code":"422","swap":true},{"code":"[45]..","swap":false,"error":true}]}',
content='{"responseHandling":[{"code":"204","swap":false},{"code":"[23]..","swap":true},{"code":"409","swap":true},{"code":"422","swap":true},{"code":"[45]..","swap":false,"error":true}]}',
)
# Create FastHTML app with HTMX extensions, MonsterUI theme, and static path

View File

@@ -200,8 +200,10 @@ def event_log_index(request: Request):
location_id = request.query_params.get("location_id", "")
event_type = request.query_params.get("event_type", "")
# "all" means show all events (no location filter)
# "all" means no filter for both location and event type
show_all = location_id == "all" or location_id == ""
if event_type == "all":
event_type = ""
# If no query param and not explicitly "all", try user defaults
if not location_id and not event_type and username:
@@ -214,21 +216,13 @@ def event_log_index(request: Request):
location_repo = LocationRepository(db)
locations = location_repo.list_active()
# Find location name if we have a specific location_id
location_name = None
if location_id and location_id != "all":
for loc in locations:
if loc.id == location_id:
location_name = loc.name
break
# Get events based on filter
events = []
if show_all or not location_id:
# Show all events (from main events table)
events = get_all_events(db, event_type=event_type or None)
elif location_id and location_name:
# Show events for specific location
elif location_id:
# Show events for specific location (location_name only used for header display)
events = get_event_log(db, location_id)
# Filter by event type if specified
if event_type:

View File

@@ -179,7 +179,7 @@ EVENT_TYPES = [
def event_type_selector(selected_event_type: str = "") -> Any:
"""Render event type filter dropdown."""
options = [Option("All types", value="", selected=not selected_event_type)]
options = [Option("All types", value="all", selected=selected_event_type in ("", "all"))]
for event_type in EVENT_TYPES:
options.append(
Option(event_type, value=event_type, selected=event_type == selected_event_type)