Frontend UX: delete-object dialog allows double-submit; login button gives no in-flight feedback #70
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Two pending-state gaps left over after #46 (object-form double-submit) and #48 (auth feedback):
Delete dialog: confirm button stays enabled during the request
web/src/objects/delete-object-dialog.tsx:58—<AlertDialogAction onClick={onConfirm}>is never disabled whiledel.isPending. A double-click fires twoDELETEs (the second 404s and flips the dialog into the error state even though the delete succeeded). Comparepublish-control.tsx, which already doesdisabled={setVisibility.isPending}on every action.Fix:
disabled={del.isPending}on the action (and arguably the cancel button),{del.isPending ? t("form.saving") : t("actions.delete")}or a dedicatedactions.deleting("Deleting…"/"Tar bort…").Check whether the shared
components/delete-confirm-dialog.tsx(used by field/vocab/term/authority rows) has the same gap — itsonConfirmis also a mutation.Login: no "Signing in…" state
web/src/auth/login-page.tsx:79-81— the button correctly disables onlogin.isPending, but the label stays "Sign in", so on a slow network there is zero feedback that anything is happening. i18n already hasauth.signingOut: "Signing out…"but nosigningIn.Fix: add
auth.signingIn("Signing in…"/"Loggar in…") toen.json+sv.jsonand render{login.isPending ? t("auth.signingIn") : t("auth.signIn")}.(Keep en/sv key parity — the #60 test will catch a one-sided addition.)
Fixed in
27205c6(merged as78f5afa).DeleteObjectDialog: cancel + confirm nowdisabled={del.isPending}, confirm label swaps to the newactions.deletingwhile in flight — double-click double-DELETE is no longer possible.DeleteConfirmDialoghad the same gap (as suspected); it now tracks a localpendingstate around the awaitedonConfirm()(cleared infinallyso the in-use error path re-enables the buttons) with the same disabled + label treatment. This covers the field/vocab/term/authority delete rows too.auth.signingIn("Signing in…" / "Loggar in…") whilelogin.isPending.actions.deleting+auth.signingInadded to bothen.jsonandsv.json(parity test green).Each fix has a test that gates the request (MSW handler awaiting a promise, or an unresolved
onConfirm), asserts the disabled + "…"-labelled state mid-flight, then releases and asserts the happy path completes.