feat: gitLab Integration Implementation / github refactor / overal improvements (#1963)

* Add GitLab integration components

Introduced PushToGitLabDialog and GitlabConnection components to handle GitLab project connections and push functionality. Includes user authentication, project handling, and UI for seamless integration with GitLab.

* Add components for GitLab connection and push dialog

Introduce `GitlabConnection` and `PushToGitLabDialog` components to handle GitLab integration. These components allow users to connect their GitLab account, manage recent projects, and push code to a GitLab repository with detailed configurations and feedback.

* Fix GitLab personal access tokens link to use correct URL

* Update GitHub push call to use new pushToRepository method

* Enhance GitLab integration with performance improvements

- Add comprehensive caching system for repositories and user data
- Implement pagination and search/filter functionality with debouncing
- Add skeleton loaders and improved loading states
- Implement retry logic for API calls with exponential backoff
- Add background refresh capabilities
- Improve error handling and user feedback
- Optimize API calls to reduce loading times

* feat: implement GitLab integration with connection management and repository handling

- Add GitLab connection UI components
- Implement GitLab API service for repository operations
- Add GitLab connection store for state management
- Update existing connection components (Vercel, Netlify)
- Add repository listing and statistics display
- Refactor GitLab components into organized folder structure

* fix: resolve GitLab deployment issues and improve user experience

- Fix DialogTitle accessibility warnings for screen readers
- Remove CORS-problematic attributes from avatar images to prevent loading errors
- Enhance GitLab API error handling with detailed error messages
- Fix project creation settings to prevent initial commit conflicts
- Add automatic GitLab connection state initialization on app startup
- Improve deployment dialog UI with better error handling and user feedback
- Add GitLab deployment source type to action runner system
- Clean up deprecated push dialog files and consolidate deployment components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: implement GitHub clone repository dialog functionality

This commit fixes the missing GitHub repository selection dialog in the "Clone a repo" feature
by implementing the same elegant interface pattern used by GitLab.

Key Changes:
- Added onCloneRepository prop support to GitHubConnection component
- Updated RepositoryCard to generate proper GitHub clone URLs (https://github.com/{full_name}.git)
- Implemented full GitHub repository selection dialog in GitCloneButton.tsx
- Added proper dialog close handling after successful clone operations
- Maintained existing GitHub connection settings page functionality

Technical Details:
- Follows same component patterns as GitLab implementation
- Uses proper TypeScript interfaces for clone URL handling
- Includes professional dialog styling with loading states
- Supports repository search, pagination, and authentication flow

The GitHub clone experience now matches GitLab's functionality, providing users with
a unified and intuitive repository selection interface across both providers.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Clean up unused connection components

- Remove ConnectionForm.tsx (unused GitHub form component)
- Remove CreateBranchDialog.tsx (unused branch creation dialog)
- Remove RepositoryDialogContext.tsx (unused context provider)
- Remove empty components/ directory

These files were not referenced anywhere in the codebase and were leftover from development.

* Remove environment variables info section from ConnectionsTab

- Remove collapsible environment variables section
- Clean up unused state and imports
- Simplify the connections tab UI

* Reorganize connections folder structure

- Create netlify/ folder and move NetlifyConnection.tsx
- Create vercel/ folder and move VercelConnection.tsx
- Add index.ts files for both netlify and vercel folders
- Update imports in ConnectionsTab.tsx to use new folder structure
- All connection components now follow consistent folder organization

---------

Co-authored-by: Hayat Bourgi <hayat.bourgi@montyholding.com>
Co-authored-by: Hayat55 <53140162+Hayat55@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Stijnus
2025-09-05 14:01:33 +02:00
committed by GitHub
parent 8a685603be
commit 3ea96506ea
46 changed files with 4401 additions and 4025 deletions

View File

@@ -6,10 +6,16 @@ import { generateId } from '~/utils/fileUtils';
import { useState } from 'react';
import { toast } from 'react-toastify';
import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { RepositorySelectionDialog } from '~/components/@settings/tabs/connections/components/RepositorySelectionDialog';
// import { RepositorySelectionDialog } from '~/components/@settings/tabs/connections/components/RepositorySelectionDialog';
import { classNames } from '~/utils/classNames';
import { Button } from '~/components/ui/Button';
import type { IChatMetadata } from '~/lib/persistence/db';
import { X, Github, GitBranch } from 'lucide-react';
// Import GitLab and GitHub connections for unified repository access
import GitLabConnection from '~/components/@settings/tabs/connections/gitlab/GitLabConnection';
import GitHubConnection from '~/components/@settings/tabs/connections/github/GitHubConnection';
const IGNORE_PATTERNS = [
'node_modules/**',
@@ -46,6 +52,7 @@ export default function GitCloneButton({ importChat, className }: GitCloneButton
const { ready, gitClone } = useGit();
const [loading, setLoading] = useState(false);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [selectedProvider, setSelectedProvider] = useState<'github' | 'gitlab' | null>(null);
const handleClone = async (repoUrl: string) => {
if (!ready) {
@@ -53,6 +60,8 @@ export default function GitCloneButton({ importChat, className }: GitCloneButton
}
setLoading(true);
setIsDialogOpen(false);
setSelectedProvider(null);
try {
const { workdir, data } = await gitClone(repoUrl);
@@ -155,8 +164,11 @@ ${escapeBoltTags(file.content)}
return (
<>
<Button
onClick={() => setIsDialogOpen(true)}
title="Clone a Git Repo"
onClick={() => {
setSelectedProvider(null);
setIsDialogOpen(true);
}}
title="Clone a repo"
variant="default"
size="lg"
className={classNames(
@@ -170,11 +182,145 @@ ${escapeBoltTags(file.content)}
)}
disabled={!ready || loading}
>
<span className="i-ph:git-branch w-4 h-4" />
Clone a Git Repo
Clone a repo
<div className="flex items-center gap-1 ml-2">
<Github className="w-4 h-4" />
<GitBranch className="w-4 h-4" />
</div>
</Button>
<RepositorySelectionDialog isOpen={isDialogOpen} onClose={() => setIsDialogOpen(false)} onSelect={handleClone} />
{/* Provider Selection Dialog */}
{isDialogOpen && !selectedProvider && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-white dark:bg-gray-950 rounded-xl shadow-xl border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor max-w-md w-full">
<div className="p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary">
Choose Repository Provider
</h3>
<button
onClick={() => setIsDialogOpen(false)}
className="p-2 rounded-lg bg-transparent hover:bg-bolt-elements-background-depth-1 dark:hover:bg-bolt-elements-background-depth-1 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary dark:hover:text-bolt-elements-textPrimary transition-all duration-200 hover:scale-105 active:scale-95"
>
<X className="w-5 h-5 transition-transform duration-200 hover:rotate-90" />
</button>
</div>
<div className="space-y-3">
<button
onClick={() => setSelectedProvider('github')}
className="w-full p-4 rounded-lg bg-bolt-elements-background-depth-1 dark:bg-bolt-elements-background-depth-1 hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-2 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor hover:border-bolt-elements-borderColorActive dark:hover:border-bolt-elements-borderColorActive transition-all duration-200 text-left group"
>
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-blue-500/10 dark:bg-blue-500/20 flex items-center justify-center group-hover:bg-blue-500/20 dark:group-hover:bg-blue-500/30 transition-colors">
<Github className="w-6 h-6 text-blue-600 dark:text-blue-400" />
</div>
<div>
<div className="font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary">
GitHub
</div>
<div className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary">
Clone from GitHub repositories
</div>
</div>
</div>
</button>
<button
onClick={() => setSelectedProvider('gitlab')}
className="w-full p-4 rounded-lg bg-bolt-elements-background-depth-1 dark:bg-bolt-elements-background-depth-1 hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-2 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor hover:border-bolt-elements-borderColorActive dark:hover:border-bolt-elements-borderColorActive transition-all duration-200 text-left group"
>
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-orange-500/10 dark:bg-orange-500/20 flex items-center justify-center group-hover:bg-orange-500/20 dark:group-hover:bg-orange-500/30 transition-colors">
<GitBranch className="w-6 h-6 text-orange-600 dark:text-orange-400" />
</div>
<div>
<div className="font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary">
GitLab
</div>
<div className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary">
Clone from GitLab repositories
</div>
</div>
</div>
</button>
</div>
</div>
</div>
</div>
)}
{/* GitHub Repository Selection */}
{isDialogOpen && selectedProvider === 'github' && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-white dark:bg-gray-950 rounded-xl shadow-xl border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor w-full max-w-4xl max-h-[90vh] overflow-hidden">
<div className="p-6 border-b border-bolt-elements-borderColor dark:border-bolt-elements-borderColor flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-blue-500/10 dark:bg-blue-500/20 flex items-center justify-center">
<Github className="w-6 h-6 text-blue-600 dark:text-blue-400" />
</div>
<div>
<h3 className="text-lg font-semibold text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary">
Import GitHub Repository
</h3>
<p className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary">
Clone a repository from GitHub to your workspace
</p>
</div>
</div>
<button
onClick={() => {
setIsDialogOpen(false);
setSelectedProvider(null);
}}
className="p-2 rounded-lg bg-transparent hover:bg-bolt-elements-background-depth-1 dark:hover:bg-bolt-elements-background-depth-1 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary dark:hover:text-bolt-elements-textPrimary transition-all duration-200 hover:scale-105 active:scale-95"
>
<X className="w-5 h-5 transition-transform duration-200 hover:rotate-90" />
</button>
</div>
<div className="p-6 max-h-[calc(90vh-140px)] overflow-y-auto">
<GitHubConnection onCloneRepository={handleClone} />
</div>
</div>
</div>
)}
{/* GitLab Repository Selection */}
{isDialogOpen && selectedProvider === 'gitlab' && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4">
<div className="bg-white dark:bg-gray-950 rounded-xl shadow-xl border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor w-full max-w-4xl max-h-[90vh] overflow-hidden">
<div className="p-6 border-b border-bolt-elements-borderColor dark:border-bolt-elements-borderColor flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-lg bg-orange-500/10 dark:bg-orange-500/20 flex items-center justify-center">
<GitBranch className="w-6 h-6 text-orange-600 dark:text-orange-400" />
</div>
<div>
<h3 className="text-lg font-semibold text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary">
Import GitLab Repository
</h3>
<p className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary">
Clone a repository from GitLab to your workspace
</p>
</div>
</div>
<button
onClick={() => {
setIsDialogOpen(false);
setSelectedProvider(null);
}}
className="p-2 rounded-lg bg-transparent hover:bg-bolt-elements-background-depth-1 dark:hover:bg-bolt-elements-background-depth-1 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary dark:hover:text-bolt-elements-textPrimary transition-all duration-200 hover:scale-105 active:scale-95"
>
<X className="w-5 h-5 transition-transform duration-200 hover:rotate-90" />
</button>
</div>
<div className="p-6 max-h-[calc(90vh-140px)] overflow-y-auto">
<GitLabConnection onCloneRepository={handleClone} />
</div>
</div>
</div>
)}
{loading && <LoadingOverlay message="Please wait while we clone the repository..." />}
</>