Skip to content

Commit 266fc9d

Browse files
committed
feat(frontend): add success state for authorization completion
1 parent 8da0e83 commit 266fc9d

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

services/frontend/src/i18n/locales/en/oauth.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export default {
1919
loading: {
2020
message: 'Loading authorization details...'
2121
},
22+
success: {
23+
title: 'Authorization Successful',
24+
description: 'You can now continue in your MCP client. This window can be closed.'
25+
},
2226
errors: {
2327
title: 'Authorization Error',
2428
missingRequestId: 'Missing request ID parameter',

services/frontend/src/views/oauth/AuthorizePage.vue

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { ref, onMounted, computed } from 'vue'
33
import { useRoute, useRouter } from 'vue-router'
44
import { useI18n } from 'vue-i18n'
5-
import { AlertTriangle, Shield } from 'lucide-vue-next'
5+
import { AlertTriangle, Shield, CheckCircle } from 'lucide-vue-next'
66
import { OAuthService, type AuthorizeDetails } from '@/services/oauthService'
77
import { TeamService, type Team } from '@/services/teamService'
88
@@ -25,6 +25,14 @@ import {
2525
SelectValue,
2626
} from '@/components/ui/select'
2727
28+
import {
29+
Empty,
30+
EmptyHeader,
31+
EmptyMedia,
32+
EmptyTitle,
33+
EmptyDescription,
34+
} from '@/components/ui/empty'
35+
2836
import { Button } from '@/components/ui/button'
2937
import { Spinner } from '@/components/ui/spinner'
3038
@@ -39,6 +47,7 @@ const teams = ref<Team[]>([])
3947
const selectedTeamId = ref<string>('')
4048
const processing = ref(false)
4149
const action = ref<'approve' | 'deny' | null>(null)
50+
const success = ref(false)
4251
4352
// Error handling helper
4453
const getErrorMessage = (err: unknown): string => {
@@ -134,6 +143,11 @@ const handleAuthorization = async (authAction: 'approve' | 'deny') => {
134143
if (result.success && result.redirect_url) {
135144
// Redirect to the MCP client callback URL
136145
window.location.href = result.redirect_url
146+
147+
// Show success state immediately since backend confirmed authorization succeeded
148+
// (MCP clients use custom protocols like vscode:// that don't navigate away from the page)
149+
processing.value = false
150+
success.value = true
137151
} else {
138152
throw new Error('Invalid response from server')
139153
}
@@ -180,6 +194,21 @@ const returnToDashboard = () => {
180194
<p class="text-gray-600">{{ t('oauth.authorize.loading.message') }}</p>
181195
</div>
182196

197+
<!-- Success State -->
198+
<div v-else-if="success" class="py-4">
199+
<Empty>
200+
<EmptyHeader>
201+
<EmptyMedia variant="icon">
202+
<CheckCircle class="text-green-600" />
203+
</EmptyMedia>
204+
<EmptyTitle>{{ t('oauth.authorize.success.title') }}</EmptyTitle>
205+
<EmptyDescription>
206+
{{ t('oauth.authorize.success.description') }}
207+
</EmptyDescription>
208+
</EmptyHeader>
209+
</Empty>
210+
</div>
211+
183212
<!-- Error State (no details loaded) -->
184213
<div v-else-if="!authorizeDetails" class="text-center py-4">
185214
<Button @click="returnToDashboard" variant="outline">

0 commit comments

Comments
 (0)