add: various improvements to connections

- improved organisation of connections (collapsibles)
- improved deploy button
- improved unique chat deployments
This commit is contained in:
KevIsDev 2025-02-25 00:41:44 +00:00
parent 96a0b2a066
commit 19137c934b
5 changed files with 95 additions and 154 deletions

View File

@ -1,73 +1,8 @@
import React, { useState, useEffect } from 'react';
import { logStore } from '~/lib/stores/logs';
import { motion } from 'framer-motion';
import { toast } from 'react-toastify';
import { GithubConnection } from './GithubConnection';
import { NetlifyConnection } from './NetlifyConnection';
interface GitHubUserResponse {
login: string;
avatar_url: string;
html_url: string;
name: string;
bio: string;
public_repos: number;
followers: number;
following: number;
created_at: string;
public_gists: number;
}
interface GitHubRepoInfo {
name: string;
full_name: string;
html_url: string;
description: string;
stargazers_count: number;
forks_count: number;
default_branch: string;
updated_at: string;
languages_url: string;
}
interface GitHubOrganization {
login: string;
avatar_url: string;
html_url: string;
}
interface GitHubEvent {
id: string;
type: string;
repo: {
name: string;
};
created_at: string;
}
interface GitHubLanguageStats {
[language: string]: number;
}
interface GitHubStats {
repos: GitHubRepoInfo[];
totalStars: number;
totalForks: number;
organizations: GitHubOrganization[];
recentActivity: GitHubEvent[];
languages: GitHubLanguageStats;
totalGists: number;
}
interface GitHubConnection {
user: GitHubUserResponse | null;
token: string;
tokenType: 'classic' | 'fine-grained';
stats?: GitHubStats;
}
export default function ConnectionsTab() {
return (
<div className="space-y-4">
{/* Header */}
@ -85,9 +20,7 @@ export default function ConnectionsTab() {
</p>
<div className="grid grid-cols-1 gap-4">
{/* GitHub Connection */}
<GithubConnection />
{/* Netlify Connection */}
<NetlifyConnection />
</div>
</div>

View File

@ -73,7 +73,6 @@ export function GithubConnection() {
});
const [isLoading, setIsLoading] = useState(true);
const [isConnecting, setIsConnecting] = useState(false);
const [isFetchingStats, setIsFetchingStats] = useState(false);
const [expandedSections, setExpandedSections] = useState({
organizations: false,
languages: false,
@ -82,16 +81,14 @@ export function GithubConnection() {
});
const toggleSection = (section: keyof typeof expandedSections) => {
setExpandedSections(prev => ({
setExpandedSections((prev) => ({
...prev,
[section]: !prev[section]
[section]: !prev[section],
}));
};
const fetchGitHubStats = async (token: string) => {
try {
setIsFetchingStats(true);
const reposResponse = await fetch(
'https://api.github.com/user/repos?sort=updated&per_page=10&affiliation=owner,organization_member,collaborator',
{
@ -168,7 +165,6 @@ export function GithubConnection() {
logStore.logError('Failed to fetch GitHub stats', { error });
toast.error('Failed to fetch GitHub statistics');
} finally {
setIsFetchingStats(false);
}
};
@ -188,6 +184,7 @@ export function GithubConnection() {
fetchGitHubStats(parsed.token);
}
}
setIsLoading(false);
}, []);
@ -401,16 +398,18 @@ export function GithubConnection() {
{/* Organizations Section */}
{connection.stats.organizations.length > 0 && (
<div className="space-y-3">
<button
<button
onClick={() => toggleSection('organizations')}
className="w-full bg-transparent text-left text-sm font-medium text-bolt-elements-textPrimary flex items-center gap-2"
>
<div className="i-ph:buildings w-4 h-4" />
Organizations ({connection.stats.organizations.length})
<div className={classNames(
"i-ph:caret-down w-4 h-4 ml-auto transition-transform",
expandedSections.organizations ? "rotate-180" : ""
)} />
<div
className={classNames(
'i-ph:caret-down w-4 h-4 ml-auto transition-transform',
expandedSections.organizations ? 'rotate-180' : '',
)}
/>
</button>
{expandedSections.organizations && (
<div className="flex flex-wrap gap-3 pb-4">
@ -433,16 +432,18 @@ export function GithubConnection() {
{/* Languages Section */}
<div className="space-y-3">
<button
<button
onClick={() => toggleSection('languages')}
className="w-full bg-transparent text-left text-sm font-medium text-bolt-elements-textPrimary flex items-center gap-2"
>
<div className="i-ph:code w-4 h-4" />
Top Languages ({Object.keys(connection.stats.languages).length})
<div className={classNames(
"i-ph:caret-down w-4 h-4 ml-auto transition-transform",
expandedSections.languages ? "rotate-180" : ""
)} />
<div
className={classNames(
'i-ph:caret-down w-4 h-4 ml-auto transition-transform',
expandedSections.languages ? 'rotate-180' : '',
)}
/>
</button>
{expandedSections.languages && (
<div className="flex flex-wrap gap-2 pb-4">
@ -463,16 +464,18 @@ export function GithubConnection() {
{/* Recent Activity Section */}
<div className="space-y-3">
<button
<button
onClick={() => toggleSection('recentActivity')}
className="w-full bg-transparent text-left text-sm font-medium text-bolt-elements-textPrimary flex items-center gap-2"
>
<div className="i-ph:activity w-4 h-4" />
Recent Activity ({connection.stats.recentActivity.length})
<div className={classNames(
"i-ph:caret-down w-4 h-4 ml-auto transition-transform",
expandedSections.recentActivity ? "rotate-180" : ""
)} />
<div
className={classNames(
'i-ph:caret-down w-4 h-4 ml-auto transition-transform',
expandedSections.recentActivity ? 'rotate-180' : '',
)}
/>
</button>
{expandedSections.recentActivity && (
<div className="space-y-3 pb-4">
@ -503,16 +506,18 @@ export function GithubConnection() {
{/* Repositories Section */}
<div className="space-y-3">
<button
<button
onClick={() => toggleSection('repositories')}
className="w-full bg-transparent text-left text-sm font-medium text-bolt-elements-textPrimary flex items-center gap-2"
>
<div className="i-ph:clock-counter-clockwise w-4 h-4" />
Recent Repositories ({connection.stats.repos.length})
<div className={classNames(
"i-ph:caret-down w-4 h-4 ml-auto transition-transform",
expandedSections.repositories ? "rotate-180" : ""
)} />
<div
className={classNames(
'i-ph:caret-down w-4 h-4 ml-auto transition-transform',
expandedSections.repositories ? 'rotate-180' : '',
)}
/>
</button>
{expandedSections.repositories && (
<div className="space-y-3">
@ -574,4 +579,4 @@ function LoadingSpinner() {
</div>
</div>
);
}
}

View File

@ -214,16 +214,18 @@ export function NetlifyConnection() {
</div>
) : (
<div>
<button
<button
onClick={() => setIsSitesExpanded(!isSitesExpanded)}
className="w-full bg-transparent text-left text-sm font-medium text-bolt-elements-textPrimary mb-3 flex items-center gap-2"
>
<div className="i-ph:buildings w-4 h-4" />
Your Sites ({connection.stats?.totalSites || 0})
<div className={classNames(
"i-ph:caret-down w-4 h-4 ml-auto transition-transform",
isSitesExpanded ? "rotate-180" : ""
)} />
<div
className={classNames(
'i-ph:caret-down w-4 h-4 ml-auto transition-transform',
isSitesExpanded ? 'rotate-180' : '',
)}
/>
</button>
{isSitesExpanded && connection.stats?.sites?.length ? (
<div className="grid gap-3">

View File

@ -33,6 +33,7 @@ export function HeaderActionButtons({}: HeaderActionButtonsProps) {
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
@ -109,6 +110,7 @@ export function HeaderActionButtons({}: HeaderActionButtonsProps) {
}
const fileContents = await getAllFiles(buildPath);
// Use chatId instead of artifact.id
const existingSiteId = localStorage.getItem(`netlify-site-${currentChatId}`);
@ -209,65 +211,64 @@ export function HeaderActionButtons({}: HeaderActionButtonsProps) {
className="px-4 hover:bg-bolt-elements-item-backgroundActive flex items-center gap-2"
>
{isDeploying ? 'Deploying...' : 'Deploy'}
<div className={classNames(
"i-ph:caret-down w-4 h-4 transition-transform",
isDropdownOpen ? "rotate-180" : ""
)} />
<div
className={classNames('i-ph:caret-down w-4 h-4 transition-transform', isDropdownOpen ? 'rotate-180' : '')}
/>
</Button>
</div>
{isDropdownOpen && (
<div className="absolute right-2 flex flex-col gap-1 z-50 p-1 mt-1 min-w-[13.5rem] bg-bolt-elements-background-depth-2 rounded-md shadow-lg bg-bolt-elements-backgroundDefault border border-bolt-elements-borderColor">
<Button
active
onClick={() => {
handleDeploy();
setIsDropdownOpen(false);
}}
disabled={isDeploying || !activePreview}
className="flex items-center w-full px-4 py-2 text-sm text-bolt-elements-textPrimary hover:bg-bolt-elements-item-backgroundActive gap-2 rounded-md"
>
<img
className="w-5 h-5"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/netlify"
/>
<span className='mx-auto'>Deploy to Netlify</span>
</Button>
<Button
active={false}
disabled
className="flex items-center w-full rounded-md px-4 py-2 text-sm text-bolt-elements-textTertiary gap-2"
>
<span className='sr-only'>Coming Soon</span>
<img
className="w-5 h-5 bg-black p-1 rounded"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/vercel/white"
alt='vercel'
/>
<span className='mx-auto'>Deploy to Vercel (Coming Soon)</span>
</Button>
<Button
active={false}
disabled
className="flex items-center w-full rounded-md px-4 py-2 text-sm text-bolt-elements-textTertiary gap-2"
>
<span className='sr-only'>Coming Soon</span>
<img
className="w-5 h-5"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/cloudflare"
alt='vercel'
/>
<span className='mx-auto'>Deploy to Cloudflare (Coming Soon)</span>
</Button>
<Button
active
onClick={() => {
handleDeploy();
setIsDropdownOpen(false);
}}
disabled={isDeploying || !activePreview}
className="flex items-center w-full px-4 py-2 text-sm text-bolt-elements-textPrimary hover:bg-bolt-elements-item-backgroundActive gap-2 rounded-md"
>
<img
className="w-5 h-5"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/netlify"
/>
<span className="mx-auto">Deploy to Netlify</span>
</Button>
<Button
active={false}
disabled
className="flex items-center w-full rounded-md px-4 py-2 text-sm text-bolt-elements-textTertiary gap-2"
>
<span className="sr-only">Coming Soon</span>
<img
className="w-5 h-5 bg-black p-1 rounded"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/vercel/white"
alt="vercel"
/>
<span className="mx-auto">Deploy to Vercel (Coming Soon)</span>
</Button>
<Button
active={false}
disabled
className="flex items-center w-full rounded-md px-4 py-2 text-sm text-bolt-elements-textTertiary gap-2"
>
<span className="sr-only">Coming Soon</span>
<img
className="w-5 h-5"
height="24"
width="24"
crossOrigin="anonymous"
src="https://cdn.simpleicons.org/cloudflare"
alt="vercel"
/>
<span className="mx-auto">Deploy to Cloudflare (Coming Soon)</span>
</Button>
</div>
)}
</div>

View File

@ -5,7 +5,7 @@ import type { ChatHistoryItem } from './useChatHistory';
export interface IChatMetadata {
gitUrl: string;
gitBranch?: string;
netlifySiteId?: string; // Add this field
netlifySiteId?: string;
}
const logger = createScopedLogger('ChatHistory');