Add loader on OAuth2 consent page submit

Track a pending allow/deny action with Button loading spinners so
users cannot double-submit while the approveConsent mutation runs or
while the browser waits on the OAuth callback redirect.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
This commit is contained in:
Cursor Agent
2026-07-02 15:03:34 +00:00
parent c27b7de1ba
commit 41d8f945c0

View File

@@ -159,14 +159,14 @@ export default function ConsentPage(props: {
const { __ } = useTranslate();
const { toast } = useToast();
const [deviceResult, setDeviceResult] = useState<"authorized" | "denied" | null>(null);
const [pendingAction, setPendingAction] = useState<"allow" | "deny" | null>(null);
const data = usePreloadedQuery<ConsentPageQuery>(consentPageQuery, props.queryRef);
usePageTitle(__("Authorize Application"));
const { node: consent } = data;
const [approveConsent, isInFlight]
= useMutation<ConsentPageMutation>(approveConsentMutation);
const [approveConsent] = useMutation<ConsentPageMutation>(approveConsentMutation);
const { oidcScopes, apiScopes } = useMemo(
() => partitionScopes(consent.scopes ?? []),
@@ -180,7 +180,9 @@ export default function ConsentPage(props: {
const handleAction = useCallback(
(approved: boolean) => {
if (!consent.id) return;
if (!consent.id || pendingAction !== null) return;
setPendingAction(approved ? "allow" : "deny");
approveConsent({
variables: {
@@ -191,6 +193,7 @@ export default function ConsentPage(props: {
},
onCompleted: (response, errors) => {
if (errors) {
setPendingAction(null);
toast({
title: __("Authorization failed"),
description: formatError(
@@ -203,6 +206,7 @@ export default function ConsentPage(props: {
}
if (!response.approveConsent) {
setPendingAction(null);
toast({
title: __("Authorization failed"),
description: __("Something went wrong. Please try again."),
@@ -221,6 +225,7 @@ export default function ConsentPage(props: {
}
},
onError: (err) => {
setPendingAction(null);
toast({
title: __("Error"),
description:
@@ -230,7 +235,7 @@ export default function ConsentPage(props: {
},
});
},
[consent, approveConsent, __, toast],
[consent, approveConsent, __, toast, pendingAction],
);
if (!consent.application || !consent.scopes) {
@@ -310,17 +315,19 @@ export default function ConsentPage(props: {
<Button
variant="secondary"
className="flex-1 h-10"
disabled={isInFlight}
disabled={pendingAction !== null}
loading={pendingAction === "deny"}
onClick={() => handleAction(false)}
>
{__("Deny")}
</Button>
<Button
className="flex-1 h-10"
disabled={isInFlight}
disabled={pendingAction !== null}
loading={pendingAction === "allow"}
onClick={() => handleAction(true)}
>
{isInFlight ? __("Authorizing...") : __("Allow")}
{__("Allow")}
</Button>
</div>