|
1 |
| -import React, { useState, useEffect } from 'react'; |
2 |
| -import { toast } from 'react-toastify'; |
3 |
| -import Cookies from 'js-cookie'; |
4 |
| -import { logStore } from '~/lib/stores/logs'; |
5 |
| - |
6 |
| -interface GitHubUserResponse { |
7 |
| - login: string; |
8 |
| - id: number; |
9 |
| - [key: string]: any; // for other properties we don't explicitly need |
10 |
| -} |
| 1 | +import React from 'react'; |
| 2 | +import { ProviderCard } from '~/lib/git/components/ProviderCard'; |
| 3 | +import { useGitProviders } from '~/lib/git/hooks/useGitProviders'; |
11 | 4 |
|
12 | 5 | export default function ConnectionsTab() {
|
13 |
| - const [githubUsername, setGithubUsername] = useState(Cookies.get('githubUsername') || ''); |
14 |
| - const [githubToken, setGithubToken] = useState(Cookies.get('githubToken') || ''); |
15 |
| - const [isConnected, setIsConnected] = useState(false); |
16 |
| - const [isVerifying, setIsVerifying] = useState(false); |
17 |
| - |
18 |
| - useEffect(() => { |
19 |
| - // Check if credentials exist and verify them |
20 |
| - if (githubUsername && githubToken) { |
21 |
| - verifyGitHubCredentials(); |
22 |
| - } |
23 |
| - }, []); |
24 |
| - |
25 |
| - const verifyGitHubCredentials = async () => { |
26 |
| - setIsVerifying(true); |
27 |
| - |
28 |
| - try { |
29 |
| - const response = await fetch('https://api.github.com/user', { |
30 |
| - headers: { |
31 |
| - Authorization: `Bearer ${githubToken}`, |
32 |
| - }, |
33 |
| - }); |
34 |
| - |
35 |
| - if (response.ok) { |
36 |
| - const data = (await response.json()) as GitHubUserResponse; |
37 |
| - |
38 |
| - if (data.login === githubUsername) { |
39 |
| - setIsConnected(true); |
40 |
| - return true; |
41 |
| - } |
42 |
| - } |
43 |
| - |
44 |
| - setIsConnected(false); |
45 |
| - |
46 |
| - return false; |
47 |
| - } catch (error) { |
48 |
| - console.error('Error verifying GitHub credentials:', error); |
49 |
| - setIsConnected(false); |
50 |
| - |
51 |
| - return false; |
52 |
| - } finally { |
53 |
| - setIsVerifying(false); |
54 |
| - } |
55 |
| - }; |
56 |
| - |
57 |
| - const handleSaveConnection = async () => { |
58 |
| - if (!githubUsername || !githubToken) { |
59 |
| - toast.error('Please provide both GitHub username and token'); |
60 |
| - return; |
61 |
| - } |
62 |
| - |
63 |
| - setIsVerifying(true); |
64 |
| - |
65 |
| - const isValid = await verifyGitHubCredentials(); |
66 |
| - |
67 |
| - if (isValid) { |
68 |
| - Cookies.set('githubUsername', githubUsername); |
69 |
| - Cookies.set('githubToken', githubToken); |
70 |
| - logStore.logSystem('GitHub connection settings updated', { |
71 |
| - username: githubUsername, |
72 |
| - hasToken: !!githubToken, |
73 |
| - }); |
74 |
| - toast.success('GitHub credentials verified and saved successfully!'); |
75 |
| - Cookies.set('git:github.com', JSON.stringify({ username: githubToken, password: 'x-oauth-basic' })); |
76 |
| - setIsConnected(true); |
77 |
| - } else { |
78 |
| - toast.error('Invalid GitHub credentials. Please check your username and token.'); |
79 |
| - } |
80 |
| - }; |
81 |
| - |
82 |
| - const handleDisconnect = () => { |
83 |
| - Cookies.remove('githubUsername'); |
84 |
| - Cookies.remove('githubToken'); |
85 |
| - Cookies.remove('git:github.com'); |
86 |
| - setGithubUsername(''); |
87 |
| - setGithubToken(''); |
88 |
| - setIsConnected(false); |
89 |
| - logStore.logSystem('GitHub connection removed'); |
90 |
| - toast.success('GitHub connection removed successfully!'); |
91 |
| - }; |
| 6 | + const { |
| 7 | + providers, |
| 8 | + credentials, |
| 9 | + expandedProviders, |
| 10 | + handleSaveConnection, |
| 11 | + handleDisconnect, |
| 12 | + updateProviderCredentials, |
| 13 | + toggleProvider, |
| 14 | + } = useGitProviders(); |
92 | 15 |
|
93 | 16 | return (
|
94 |
| - <div className="p-4 mb-4 border border-bolt-elements-borderColor rounded-lg bg-bolt-elements-background-depth-3"> |
95 |
| - <h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">GitHub Connection</h3> |
96 |
| - <div className="flex mb-4"> |
97 |
| - <div className="flex-1 mr-2"> |
98 |
| - <label className="block text-sm text-bolt-elements-textSecondary mb-1">GitHub Username:</label> |
99 |
| - <input |
100 |
| - type="text" |
101 |
| - value={githubUsername} |
102 |
| - onChange={(e) => setGithubUsername(e.target.value)} |
103 |
| - disabled={isVerifying} |
104 |
| - className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor disabled:opacity-50" |
105 |
| - /> |
106 |
| - </div> |
107 |
| - <div className="flex-1"> |
108 |
| - <label className="block text-sm text-bolt-elements-textSecondary mb-1">Personal Access Token:</label> |
109 |
| - <input |
110 |
| - type="password" |
111 |
| - value={githubToken} |
112 |
| - onChange={(e) => setGithubToken(e.target.value)} |
113 |
| - disabled={isVerifying} |
114 |
| - className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor disabled:opacity-50" |
115 |
| - /> |
116 |
| - </div> |
117 |
| - </div> |
118 |
| - <div className="flex mb-4 items-center"> |
119 |
| - {!isConnected ? ( |
120 |
| - <button |
121 |
| - onClick={handleSaveConnection} |
122 |
| - disabled={isVerifying || !githubUsername || !githubToken} |
123 |
| - className="bg-bolt-elements-button-primary-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-button-primary-text disabled:opacity-50 disabled:cursor-not-allowed flex items-center" |
124 |
| - > |
125 |
| - {isVerifying ? ( |
126 |
| - <> |
127 |
| - <div className="i-ph:spinner animate-spin mr-2" /> |
128 |
| - Verifying... |
129 |
| - </> |
130 |
| - ) : ( |
131 |
| - 'Connect' |
132 |
| - )} |
133 |
| - </button> |
134 |
| - ) : ( |
135 |
| - <button |
136 |
| - onClick={handleDisconnect} |
137 |
| - className="bg-bolt-elements-button-danger-background rounded-lg px-4 py-2 mr-2 transition-colors duration-200 hover:bg-bolt-elements-button-danger-backgroundHover text-bolt-elements-button-danger-text" |
138 |
| - > |
139 |
| - Disconnect |
140 |
| - </button> |
141 |
| - )} |
142 |
| - {isConnected && ( |
143 |
| - <span className="text-sm text-green-600 flex items-center"> |
144 |
| - <div className="i-ph:check-circle mr-1" /> |
145 |
| - Connected to GitHub |
146 |
| - </span> |
147 |
| - )} |
148 |
| - </div> |
| 17 | + <div className="space-y-4"> |
| 18 | + <div className="i-ph:github-logo-duotone hidden" /> |
| 19 | + // Preloading icons otherwise they will not be displayed. Need fixing. |
| 20 | + <div className="i-ph:gitlab-logo-duotone hidden" /> |
| 21 | + // Preloading icons otherwise they will not be displayed. Need fixing. |
| 22 | + {Object.entries(providers).map(([key, plugin]) => ( |
| 23 | + <ProviderCard |
| 24 | + key={key} |
| 25 | + provider={plugin.provider} |
| 26 | + credentials={credentials[key]} |
| 27 | + isExpanded={expandedProviders[key]} |
| 28 | + onToggle={() => toggleProvider(key)} |
| 29 | + onUpdateCredentials={(updates) => updateProviderCredentials(key, updates)} |
| 30 | + onSave={() => handleSaveConnection(key)} |
| 31 | + onDisconnect={() => handleDisconnect(key)} |
| 32 | + /> |
| 33 | + ))} |
149 | 34 | </div>
|
150 | 35 | );
|
151 | 36 | }
|
0 commit comments