History

Share OAuth sign-in button UI (#451)

Rhys Sullivan committed 6 months ago

Commit d8df88b1 parent 9638cc34 files · +52 −39Browse files

Unified · Split

4 files
  1. packages/plugins/google-discovery/src/react/GoogleDiscoverySignInButton.tsx +9 −13
  2. packages/plugins/graphql/src/react/GraphqlSignInButton.tsx +7 −13
  3. packages/plugins/mcp/src/react/McpSignInButton.tsx +9 −13
  4. packages/react/src/plugins/oauth-sign-in.tsx +27 −0
packages/plugins/google-discovery/src/react/GoogleDiscoverySignInButton.tsx+9−13
@@ -4,8 +4,8 @@ import { useAtomSet, useAtomValue, Result } from "@effect-atom/atom-react"; · 3 unmodified lines
44 import { connectionsAtom } from "@executor/react/api/atoms";
55 import { useScope } from "@executor/react/api/scope-context";
66 import { connectionWriteKeys, sourceWriteKeys } from "@executor/react/api/reactivity-keys";
7−import { Button } from "@executor/react/components/button";
87 import {
8+ OAuthSignInButton,
99 oauthCallbackUrl,
1010 useOAuthPopupFlow,
1111 type OAuthCompletionPayload,
@@ -96,17 +96,13 @@ export default function GoogleDiscoverySignInButton(props: { sourceId: string }) · 84 unmodified lines
9696 if (!oauth2) return null;
9797
9898 return (
99− <div className="flex items-center gap-2">
100− {oauth.error && <span className="text-xs text-destructive">{oauth.error}</span>}
101− <Button variant="outline" size="sm" onClick={() => void handleSignIn()} disabled={oauth.busy}>
102− {oauth.busy
103− ? isConnected
104− ? "Reconnecting…"
105− : "Signing in…"
106− : isConnected
107− ? "Reconnect"
108− : "Sign in"}
109− </Button>
110− </div>
99+ <OAuthSignInButton
100+ busy={oauth.busy}
101+ error={oauth.error}
102+ isConnected={isConnected}
103+ onSignIn={() => void handleSignIn()}
104+ reconnectingLabel="Reconnecting…"
105+ signingInLabel="Signing in…"
106+ />
111107 );
112108 }
packages/plugins/graphql/src/react/GraphqlSignInButton.tsx+7−13
@@ -4,8 +4,8 @@ import { useAtomSet, useAtomValue, Result } from "@effect-atom/atom-react"; · 3 unmodified lines
44 import { connectionsAtom } from "@executor/react/api/atoms";
55 import { useScope } from "@executor/react/api/scope-context";
66 import { sourceWriteKeys } from "@executor/react/api/reactivity-keys";
7−import { Button } from "@executor/react/components/button";
87 import {
8+ OAuthSignInButton,
99 oauthCallbackUrl,
1010 oauthConnectionId,
1111 useOAuthPopupFlow,
@@ -64,17 +64,11 @@ export default function GraphqlSignInButton(props: { sourceId: string }) { · 52 unmodified lines
6464 if (!oauth2) return null;
6565
6666 return (
67− <div className="flex items-center gap-2">
68− {oauth.error && <span className="text-xs text-destructive">{oauth.error}</span>}
69− <Button variant="outline" size="sm" onClick={() => void handleSignIn()} disabled={oauth.busy}>
70− {oauth.busy
71− ? isConnected
72− ? "Reconnecting..."
73− : "Signing in..."
74− : isConnected
75− ? "Reconnect"
76− : "Sign in"}
77− </Button>
78− </div>
67+ <OAuthSignInButton
68+ busy={oauth.busy}
69+ error={oauth.error}
70+ isConnected={isConnected}
71+ onSignIn={() => void handleSignIn()}
72+ />
7973 );
8074 }
packages/plugins/mcp/src/react/McpSignInButton.tsx+9−13
@@ -4,8 +4,8 @@ import { useAtomSet, useAtomValue, Result } from "@effect-atom/atom-react"; · 3 unmodified lines
44 import { useScope } from "@executor/react/api/scope-context";
55 import { sourceWriteKeys } from "@executor/react/api/reactivity-keys";
66 import { connectionsAtom } from "@executor/react/api/atoms";
7−import { Button } from "@executor/react/components/button";
87 import {
8+ OAuthSignInButton,
99 oauthCallbackUrl,
1010 oauthConnectionId,
1111 useOAuthPopupFlow,
@@ -75,17 +75,13 @@ export default function McpSignInButton(props: { sourceId: string }) { · 63 unmodified lines
7575 if (!oauth2) return null;
7676
7777 return (
78− <div className="flex items-center gap-2">
79− {oauth.error && <span className="text-xs text-destructive">{oauth.error}</span>}
80− <Button variant="outline" size="sm" onClick={() => void handleSignIn()} disabled={oauth.busy}>
81− {oauth.busy
82− ? isConnected
83− ? "Reconnecting…"
84− : "Signing in…"
85− : isConnected
86− ? "Reconnect"
87− : "Sign in"}
88− </Button>
89− </div>
78+ <OAuthSignInButton
79+ busy={oauth.busy}
80+ error={oauth.error}
81+ isConnected={isConnected}
82+ onSignIn={() => void handleSignIn()}
83+ reconnectingLabel="Reconnecting…"
84+ signingInLabel="Signing in…"
85+ />
9086 );
9187 }
packages/react/src/plugins/oauth-sign-in.tsx+27−0
@@ -4,6 +4,7 @@ import { useAtomSet } from "@effect-atom/atom-react"; · 3 unmodified lines
44 import { cancelOAuth, startOAuth } from "../api/atoms";
55 import { openOAuthPopup, type OAuthPopupResult } from "../api/oauth-popup";
66 import { useScope } from "../api/scope-context";
7+import { Button } from "../components/button";
78 import { OAUTH_POPUP_MESSAGE_TYPE, type OAuthStrategy } from "@executor/sdk";
89
910 type SecretBackedValue =
@@ -231,3 +232,29 @@ export function useOAuthPopupFlow< · 221 unmodified lines
231232 cancel,
232233 };
233234 }
235+
236+export function OAuthSignInButton(props: {
237+ readonly busy: boolean;
238+ readonly error: string | null;
239+ readonly isConnected: boolean;
240+ readonly onSignIn: () => void;
241+ readonly reconnectingLabel?: string;
242+ readonly signingInLabel?: string;
243+ readonly reconnectLabel?: string;
244+ readonly signInLabel?: string;
245+}) {
246+ return (
247+ <div className="flex items-center gap-2">
248+ {props.error && <span className="text-xs text-destructive">{props.error}</span>}
249+ <Button variant="outline" size="sm" onClick={props.onSignIn} disabled={props.busy}>
250+ {props.busy
251+ ? props.isConnected
252+ ? (props.reconnectingLabel ?? "Reconnecting...")
253+ : (props.signingInLabel ?? "Signing in...")
254+ : props.isConnected
255+ ? (props.reconnectLabel ?? "Reconnect")
256+ : (props.signInLabel ?? "Sign in")}
257+ </Button>
258+ </div>
259+ );
260+}