From 068066de734cf47791fd9322018026f2fb670eaa Mon Sep 17 00:00:00 2001 From: mrzmyr Date: Tue, 12 May 2026 09:43:04 +0200 Subject: [PATCH] Show loading badge while credentials resolve --- .../graphql/src/react/GraphqlSourceSummary.tsx | 5 ++--- .../plugins/mcp/src/react/McpSourceSummary.tsx | 5 ++--- .../openapi/src/react/OpenApiSourceSummary.tsx | 16 +++------------- .../src/plugins/source-credential-status.tsx | 11 +++++++++++ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx b/packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx index 5e47539de..008d0b2e5 100644 --- a/packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx +++ b/packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx @@ -4,6 +4,7 @@ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; import { connectionsAtom } from "@executor-js/react/api/atoms"; import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context"; import { + SourceCredentialLoadingBadge, SourceCredentialNotice, SourceCredentialStatusBadge, missingSourceCredentialLabels, @@ -53,9 +54,7 @@ export default function GraphqlSourceSummary(props: { const slots = sourceCredentialSlots(source as StoredGraphqlSource); if (slots.length === 0) return null; if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) { - return props.variant === "panel" ? null : ( - - ); + return props.variant === "panel" ? null : ; } const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const)); diff --git a/packages/plugins/mcp/src/react/McpSourceSummary.tsx b/packages/plugins/mcp/src/react/McpSourceSummary.tsx index cdae6d083..ea4be0d61 100644 --- a/packages/plugins/mcp/src/react/McpSourceSummary.tsx +++ b/packages/plugins/mcp/src/react/McpSourceSummary.tsx @@ -4,6 +4,7 @@ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; import { connectionsAtom } from "@executor-js/react/api/atoms"; import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context"; import { + SourceCredentialLoadingBadge, SourceCredentialNotice, SourceCredentialStatusBadge, missingSourceCredentialLabels, @@ -70,9 +71,7 @@ export default function McpSourceSummary(props: { const slots = sourceCredentialSlots(source as McpStoredSourceSchemaType); if (slots.length === 0) return null; if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) { - return props.variant === "panel" ? null : ( - - ); + return props.variant === "panel" ? null : ; } const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const)); diff --git a/packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx b/packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx index cdcdd7d15..2247dd298 100644 --- a/packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx +++ b/packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx @@ -6,6 +6,7 @@ import { Badge } from "@executor-js/react/components/badge"; import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context"; import { ScopeId } from "@executor-js/sdk/core"; import { + SourceCredentialLoadingBadge, SourceCredentialNotice, SourceCredentialStatusBadge, missingSourceCredentialLabels, @@ -20,17 +21,6 @@ function OAuthBadge() { return OAuth; } -function CheckingCredentialsBadge() { - return ( - - Checking credentials - - ); -} - const effectiveClientSecretSlot = (oauth2: { readonly securitySchemeName: string; readonly clientSecretSlot: string | null; @@ -92,12 +82,12 @@ export default function OpenApiSourceSummary(props: { const bindingsLoaded = AsyncResult.isSuccess(bindingsResult); const connectionsLoaded = AsyncResult.isSuccess(connectionsResult); if (!bindingsLoaded) { - return props.variant === "panel" ? null : ; + return props.variant === "panel" ? null : ; } const bindings = AsyncResult.isSuccess(bindingsResult) ? bindingsResult.value : []; if (oauth2 && !connectionsLoaded) { - return props.variant === "panel" ? null : ; + return props.variant === "panel" ? null : ; } const connections = AsyncResult.isSuccess(connectionsResult) ? connectionsResult.value : []; const liveConnectionIds = new Set(connections.map((connection) => connection.id)); diff --git a/packages/react/src/plugins/source-credential-status.tsx b/packages/react/src/plugins/source-credential-status.tsx index 99ac68cf0..9aa2fb0c4 100644 --- a/packages/react/src/plugins/source-credential-status.tsx +++ b/packages/react/src/plugins/source-credential-status.tsx @@ -7,6 +7,17 @@ export { type SourceCredentialSlot, } from "./source-credential-status-core"; +export function SourceCredentialLoadingBadge() { + return ( + + loading + + ); +} + export function SourceCredentialStatusBadge(props: { readonly missing: readonly string[] }) { if (props.missing.length === 0) { return (