History

Show loading badge while credentials resolve (#772)

Moritz Meyer committed 5 months ago

Commit eefb8b51 parent 81b628f4 files · +18 −19Browse files

Unified · Split

4 files
  1. packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx +2 −3
  2. packages/plugins/mcp/src/react/McpSourceSummary.tsx +2 −3
  3. packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx +3 −13
  4. packages/react/src/plugins/source-credential-status.tsx +11 −0
packages/plugins/graphql/src/react/GraphqlSourceSummary.tsx+2−3
@@ -4,6 +4,7 @@ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; · 3 unmodified lines
44 import { connectionsAtom } from "@executor-js/react/api/atoms";
55 import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context";
66 import {
7+ SourceCredentialLoadingBadge,
78 SourceCredentialNotice,
89 SourceCredentialStatusBadge,
910 missingSourceCredentialLabels,
@@ -53,9 +54,7 @@ export default function GraphqlSourceSummary(props: { · 43 unmodified lines
5354 const slots = sourceCredentialSlots(source as StoredGraphqlSource);
5455 if (slots.length === 0) return null;
5556 if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) {
56− return props.variant === "panel" ? null : (
57− <SourceCredentialStatusBadge missing={["credentials"]} />
58− );
57+ return props.variant === "panel" ? null : <SourceCredentialLoadingBadge />;
5958 }
6059
6160 const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const));
packages/plugins/mcp/src/react/McpSourceSummary.tsx+2−3
@@ -5,6 +5,7 @@ import { connectionsAtom } from "@executor-js/react/api/atoms"; · 4 unmodified lines
55 import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context";
66 import { Button } from "@executor-js/react/components/button";
77 import {
8+ SourceCredentialLoadingBadge,
89 SourceCredentialNotice,
910 SourceCredentialStatusBadge,
1011 missingSourceCredentialLabels,
@@ -72,9 +73,7 @@ export default function McpSourceSummary(props: { · 61 unmodified lines
7273 const slots = sourceCredentialSlots(source as McpStoredSourceSchemaType);
7374 if (slots.length === 0) return null;
7475 if (!AsyncResult.isSuccess(bindingsResult) || !AsyncResult.isSuccess(connectionsResult)) {
75− return props.variant === "panel" ? null : (
76− <SourceCredentialStatusBadge missing={["credentials"]} />
77− );
76+ return props.variant === "panel" ? null : <SourceCredentialLoadingBadge />;
7877 }
7978
8079 const scopeRanks = new Map(scopeStack.map((scope, index) => [scope.id, index] as const));
packages/plugins/openapi/src/react/OpenApiSourceSummary.tsx+3−13
@@ -6,6 +6,7 @@ import { Badge } from "@executor-js/react/components/badge"; · 5 unmodified lines
66 import { useScope, useScopeStack, useUserScope } from "@executor-js/react/api/scope-context";
77 import { ScopeId } from "@executor-js/sdk/shared";
88 import {
9+ SourceCredentialLoadingBadge,
910 SourceCredentialNotice,
1011 SourceCredentialStatusBadge,
1112 missingSourceCredentialLabels,
@@ -20,17 +21,6 @@ function OAuthBadge() { · 8 unmodified lines
2021 return <Badge variant="secondary">OAuth</Badge>;
2122 }
2223
23−function CheckingCredentialsBadge() {
24− return (
25− <Badge
26− variant="outline"
27− className="border-border bg-muted/50 text-[10px] text-muted-foreground"
28− >
29− Checking credentials
30− </Badge>
31− );
32−}
33−
3424 const effectiveClientSecretSlot = (oauth2: {
3525 readonly securitySchemeName: string;
3626 readonly clientSecretSlot: string | null;
@@ -92,12 +82,12 @@ export default function OpenApiSourceSummary(props: { · 55 unmodified lines
9282 const bindingsLoaded = AsyncResult.isSuccess(bindingsResult);
9383 const connectionsLoaded = AsyncResult.isSuccess(connectionsResult);
9484 if (!bindingsLoaded) {
95− return props.variant === "panel" ? null : <CheckingCredentialsBadge />;
85+ return props.variant === "panel" ? null : <SourceCredentialLoadingBadge />;
9686 }
9787
9888 const bindings = AsyncResult.isSuccess(bindingsResult) ? bindingsResult.value : [];
9989 if (oauth2 && !connectionsLoaded) {
100− return props.variant === "panel" ? null : <CheckingCredentialsBadge />;
90+ return props.variant === "panel" ? null : <SourceCredentialLoadingBadge />;
10191 }
10292 const connections = AsyncResult.isSuccess(connectionsResult) ? connectionsResult.value : [];
10393 const liveConnectionIds = new Set(connections.map((connection) => connection.id));
packages/react/src/plugins/source-credential-status.tsx+11−0
@@ -8,6 +8,17 @@ export { · 7 unmodified lines
88 type SourceCredentialSlot,
99 } from "./source-credential-status-core";
1010
11+export function SourceCredentialLoadingBadge() {
12+ return (
13+ <Badge
14+ variant="outline"
15+ className="animate-pulse border-border bg-muted/40 text-[10px] text-muted-foreground"
16+ >
17+ loading
18+ </Badge>
19+ );
20+}
21+
1122 export function SourceCredentialStatusBadge(props: { readonly missing: readonly string[] }) {
1223 if (props.missing.length === 0) {
1324 return (