add: connection improvements
Improve connections visually and functionality
This commit is contained in:
@@ -67,124 +67,6 @@ interface GitHubConnection {
|
||||
}
|
||||
|
||||
export default function ConnectionsTab() {
|
||||
const [connection, setConnection] = useState<GitHubConnection>({
|
||||
user: null,
|
||||
token: '',
|
||||
tokenType: 'classic',
|
||||
});
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
// Load saved connection on mount
|
||||
useEffect(() => {
|
||||
const savedConnection = localStorage.getItem('github_connection');
|
||||
|
||||
if (savedConnection) {
|
||||
const parsed = JSON.parse(savedConnection);
|
||||
|
||||
// Ensure backward compatibility with existing connections
|
||||
if (!parsed.tokenType) {
|
||||
parsed.tokenType = 'classic';
|
||||
}
|
||||
|
||||
setConnection(parsed);
|
||||
|
||||
if (parsed.user && parsed.token) {
|
||||
fetchGitHubStats(parsed.token);
|
||||
}
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
}, []);
|
||||
|
||||
const fetchGitHubStats = async (token: string) => {
|
||||
try {
|
||||
// Fetch repositories - only owned by the authenticated user
|
||||
const reposResponse = await fetch(
|
||||
'https://api.github.com/user/repos?sort=updated&per_page=10&affiliation=owner,organization_member,collaborator',
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!reposResponse.ok) {
|
||||
throw new Error('Failed to fetch repositories');
|
||||
}
|
||||
|
||||
const repos = (await reposResponse.json()) as GitHubRepoInfo[];
|
||||
|
||||
// Fetch organizations
|
||||
const orgsResponse = await fetch('https://api.github.com/user/orgs', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!orgsResponse.ok) {
|
||||
throw new Error('Failed to fetch organizations');
|
||||
}
|
||||
|
||||
const organizations = (await orgsResponse.json()) as GitHubOrganization[];
|
||||
|
||||
// Fetch recent activity
|
||||
const eventsResponse = await fetch('https://api.github.com/users/' + connection.user?.login + '/events/public', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!eventsResponse.ok) {
|
||||
throw new Error('Failed to fetch events');
|
||||
}
|
||||
|
||||
const recentActivity = ((await eventsResponse.json()) as GitHubEvent[]).slice(0, 5);
|
||||
|
||||
// Fetch languages for each repository
|
||||
const languagePromises = repos.map((repo) =>
|
||||
fetch(repo.languages_url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}).then((res) => res.json() as Promise<Record<string, number>>),
|
||||
);
|
||||
|
||||
const repoLanguages = await Promise.all(languagePromises);
|
||||
const languages: GitHubLanguageStats = {};
|
||||
|
||||
repoLanguages.forEach((repoLang) => {
|
||||
Object.entries(repoLang).forEach(([lang, bytes]) => {
|
||||
languages[lang] = (languages[lang] || 0) + bytes;
|
||||
});
|
||||
});
|
||||
|
||||
// Calculate total stats
|
||||
const totalStars = repos.reduce((acc, repo) => acc + repo.stargazers_count, 0);
|
||||
const totalForks = repos.reduce((acc, repo) => acc + repo.forks_count, 0);
|
||||
const totalGists = connection.user?.public_gists || 0;
|
||||
|
||||
setConnection((prev) => ({
|
||||
...prev,
|
||||
stats: {
|
||||
repos,
|
||||
totalStars,
|
||||
totalForks,
|
||||
organizations,
|
||||
recentActivity,
|
||||
languages,
|
||||
totalGists,
|
||||
},
|
||||
}));
|
||||
} catch (error) {
|
||||
logStore.logError('Failed to fetch GitHub stats', { error });
|
||||
toast.error('Failed to fetch GitHub statistics');
|
||||
} finally {
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -211,14 +93,3 @@ export default function ConnectionsTab() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function LoadingSpinner() {
|
||||
return (
|
||||
<div className="flex items-center justify-center p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="i-ph:spinner-gap-bold animate-spin w-4 h-4" />
|
||||
<span className="text-bolt-elements-textSecondary">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user