Add loading state indicators to all form submit buttons
Add hx_disabled_elt="this" to submit buttons across all forms to disable them during form submission, preventing double-clicks and providing visual feedback that the action is processing. Buttons updated: - actions.py: promote, cohort, hatch, tag-add, tag-end, attrs, outcome, status-correct forms and their diff_panel confirmations - eggs.py: collect and sell forms - feed.py: give and purchase forms - locations.py: create and rename forms - move.py: move form and diff_panel confirmation - products.py: create form - registry.py: filter apply button 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -266,7 +266,7 @@ def cohort_form(
|
|||||||
# Hidden nonce for idempotency
|
# Hidden nonce for idempotency
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Create Cohort", type="submit", cls=ButtonT.primary),
|
Button("Create Cohort", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -395,7 +395,7 @@ def hatch_form(
|
|||||||
# Hidden nonce for idempotency
|
# Hidden nonce for idempotency
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Hatch", type="submit", cls=ButtonT.primary),
|
Button("Record Hatch", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -522,6 +522,7 @@ def promote_form(
|
|||||||
"Save Changes" if is_rename else "Promote to Identified",
|
"Save Changes" if is_rename else "Promote to Identified",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.primary,
|
cls=ButtonT.primary,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
@@ -648,7 +649,7 @@ def tag_add_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Add Tag", type="submit", cls=ButtonT.primary),
|
Button("Add Tag", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -712,6 +713,7 @@ def tag_add_diff_panel(
|
|||||||
f"Confirm Tag ({diff.server_count} animals)",
|
f"Confirm Tag ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.primary,
|
cls=ButtonT.primary,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
@@ -867,7 +869,13 @@ def tag_end_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("End Tag", type="submit", cls=ButtonT.primary, disabled=not active_tags),
|
Button(
|
||||||
|
"End Tag",
|
||||||
|
type="submit",
|
||||||
|
cls=ButtonT.primary,
|
||||||
|
disabled=not active_tags,
|
||||||
|
hx_disabled_elt="this",
|
||||||
|
),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -931,6 +939,7 @@ def tag_end_diff_panel(
|
|||||||
f"Confirm End Tag ({diff.server_count} animals)",
|
f"Confirm End Tag ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.primary,
|
cls=ButtonT.primary,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
@@ -1110,7 +1119,7 @@ def attrs_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Update Attributes", type="submit", cls=ButtonT.primary),
|
Button("Update Attributes", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -1180,6 +1189,7 @@ def attrs_diff_panel(
|
|||||||
f"Confirm Update ({diff.server_count} animals)",
|
f"Confirm Update ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.primary,
|
cls=ButtonT.primary,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
@@ -1405,7 +1415,7 @@ def outcome_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Outcome", type="submit", cls=ButtonT.destructive),
|
Button("Record Outcome", type="submit", cls=ButtonT.destructive, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -1484,6 +1494,7 @@ def outcome_diff_panel(
|
|||||||
f"Confirm Outcome ({diff.server_count} animals)",
|
f"Confirm Outcome ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.destructive,
|
cls=ButtonT.destructive,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
@@ -1626,7 +1637,7 @@ def status_correct_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Correct Status", type="submit", cls=ButtonT.destructive),
|
Button("Correct Status", type="submit", cls=ButtonT.destructive, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -1693,6 +1704,7 @@ def status_correct_diff_panel(
|
|||||||
f"Confirm Correction ({diff.server_count} animals)",
|
f"Confirm Correction ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.destructive,
|
cls=ButtonT.destructive,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ def harvest_form(
|
|||||||
# Hidden nonce for idempotency
|
# Hidden nonce for idempotency
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Harvest", type="submit", cls=ButtonT.primary),
|
Button("Record Harvest", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -347,7 +347,7 @@ def sell_form(
|
|||||||
# Hidden nonce for idempotency
|
# Hidden nonce for idempotency
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Sale", type="submit", cls=ButtonT.primary),
|
Button("Record Sale", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ def give_feed_form(
|
|||||||
# Hidden nonce
|
# Hidden nonce
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Feed Given", type="submit", cls=ButtonT.primary),
|
Button("Record Feed Given", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
cls="space-y-4",
|
cls="space-y-4",
|
||||||
@@ -404,7 +404,7 @@ def purchase_feed_form(
|
|||||||
# Hidden nonce
|
# Hidden nonce
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Purchase", type="submit", cls=ButtonT.primary),
|
Button("Record Purchase", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
cls="space-y-4",
|
cls="space-y-4",
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ def location_list(
|
|||||||
placeholder="Enter location name",
|
placeholder="Enter location name",
|
||||||
),
|
),
|
||||||
Hidden(name="nonce", value=str(uuid4())),
|
Hidden(name="nonce", value=str(uuid4())),
|
||||||
Button("Create Location", type="submit", cls=ButtonT.primary),
|
Button("Create Location", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
hx_post="/actions/location-created",
|
hx_post="/actions/location-created",
|
||||||
hx_target="#location-list",
|
hx_target="#location-list",
|
||||||
hx_swap="outerHTML",
|
hx_swap="outerHTML",
|
||||||
@@ -160,7 +160,7 @@ def rename_form(
|
|||||||
Hidden(name="nonce", value=str(uuid4())),
|
Hidden(name="nonce", value=str(uuid4())),
|
||||||
DivFullySpaced(
|
DivFullySpaced(
|
||||||
Button("Cancel", type="button", cls=ButtonT.ghost, hx_get="/locations"),
|
Button("Cancel", type="button", cls=ButtonT.ghost, hx_get="/locations"),
|
||||||
Button("Rename", type="submit", cls=ButtonT.primary),
|
Button("Rename", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
),
|
),
|
||||||
hx_post="/actions/location-renamed",
|
hx_post="/actions/location-renamed",
|
||||||
hx_target="#location-list",
|
hx_target="#location-list",
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ def move_form(
|
|||||||
Hidden(name="confirmed", value=""),
|
Hidden(name="confirmed", value=""),
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Move Animals", type="submit", cls=ButtonT.primary),
|
Button("Move Animals", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
@@ -263,6 +263,7 @@ def diff_panel(
|
|||||||
f"Confirm Move ({diff.server_count} animals)",
|
f"Confirm Move ({diff.server_count} animals)",
|
||||||
type="submit",
|
type="submit",
|
||||||
cls=ButtonT.primary,
|
cls=ButtonT.primary,
|
||||||
|
hx_disabled_elt="this",
|
||||||
),
|
),
|
||||||
cls="flex gap-3 mt-4",
|
cls="flex gap-3 mt-4",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ def product_sold_form(
|
|||||||
# Hidden nonce for idempotency
|
# Hidden nonce for idempotency
|
||||||
Hidden(name="nonce", value=str(ULID())),
|
Hidden(name="nonce", value=str(ULID())),
|
||||||
# Submit button
|
# Submit button
|
||||||
Button("Record Sale", type="submit", cls=ButtonT.primary),
|
Button("Record Sale", type="submit", cls=ButtonT.primary, hx_disabled_elt="this"),
|
||||||
# Form submission via standard action/method (hx-boost handles AJAX)
|
# Form submission via standard action/method (hx-boost handles AJAX)
|
||||||
action=action,
|
action=action,
|
||||||
method="post",
|
method="post",
|
||||||
|
|||||||
@@ -107,7 +107,12 @@ def registry_header(filter_str: str, total_count: int) -> Div:
|
|||||||
),
|
),
|
||||||
# Buttons container
|
# Buttons container
|
||||||
Div(
|
Div(
|
||||||
Button("Apply", type="submit", cls=f"{ButtonT.primary} px-4"),
|
Button(
|
||||||
|
"Apply",
|
||||||
|
type="submit",
|
||||||
|
cls=f"{ButtonT.primary} px-4",
|
||||||
|
hx_disabled_elt="this",
|
||||||
|
),
|
||||||
# Clear button (only shown if filter is active)
|
# Clear button (only shown if filter is active)
|
||||||
A(
|
A(
|
||||||
"Clear",
|
"Clear",
|
||||||
|
|||||||
Reference in New Issue
Block a user