diff --git a/app/components/@settings/tabs/connections/components/PushToGitLabDialog.tsx b/app/components/@settings/tabs/connections/components/PushToGitLabDialog.tsx index 7c3fe941..c7c835ae 100644 --- a/app/components/@settings/tabs/connections/components/PushToGitLabDialog.tsx +++ b/app/components/@settings/tabs/connections/components/PushToGitLabDialog.tsx @@ -78,11 +78,11 @@ export function PushToGitLabDialog({ isOpen, onClose, onPush }: PushToGitLabDial setIsFetchingProjects(true); const response = await fetch( - 'https://gitlab.com/api/v4/projects?membership=true&order_by=updated_at&sort=desc&per_page=5', + 'https://gitlab.com/api/v4/projects?membership=true&min_access_level=20&order_by=last_activity_at&per_page=5&simple=true', { headers: { Accept: 'application/json', - 'Private-Token': token.trim(), + Authorization: `Bearer ${token.trim()}`, }, }, ); @@ -91,7 +91,7 @@ export function PushToGitLabDialog({ isOpen, onClose, onPush }: PushToGitLabDial const errorData = await response.json().catch(() => ({})); if (response.status === 401) { - toast.error('GitLab token expired. Please reconnect your account.'); + toast.error('GitLab token expired or invalid. Please reconnect your account.'); // Clear invalid token const connection = getLocalStorage('gitlab_connection'); @@ -109,6 +109,8 @@ export function PushToGitLabDialog({ isOpen, onClose, onPush }: PushToGitLabDial toast.error(`Failed to fetch projects: ${response.statusText}`); } + setIsFetchingProjects(false); + return; } diff --git a/app/components/@settings/tabs/connections/components/RepositorySelectionDialog.tsx b/app/components/@settings/tabs/connections/components/RepositorySelectionDialog.tsx index 00096607..92a48036 100644 --- a/app/components/@settings/tabs/connections/components/RepositorySelectionDialog.tsx +++ b/app/components/@settings/tabs/connections/components/RepositorySelectionDialog.tsx @@ -484,15 +484,6 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit const [pendingGitUrl, setPendingGitUrl] = useState(''); const [showAuthDialog, setShowAuthDialog] = useState(false); const [showAuthGitlabDialog, setShowAuthGitlabDialog] = useState(false); - const [hasGitlabConnection, setHasGitlabConnection] = useState(false); - - useEffect(() => { - const savedConnection = localStorage.getItem('gitlab_connection'); - - if (savedConnection) { - setHasGitlabConnection(true); - } - }, []); // Handle GitHub auth dialog close and refresh repositories const handleAuthDialogClose = (category: 'github' | 'gitlab') => { @@ -625,11 +616,11 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit // Fetch both GitHub and GitLab repositories when the dialog opens const githubConnection = getLocalStorage('github_connection'); const gitlabConnection = getLocalStorage('gitlab_connection'); - + if (githubConnection?.token) { fetchUserRepos('github'); } - + if (gitlabConnection?.token) { fetchUserRepos('gitlab'); } @@ -641,7 +632,10 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit const gitlabConnection = getLocalStorage('gitlab_connection'); if (!gitlabConnection?.token && !githubConnection?.token) { - toast.error('Please connect your Gitlab our Github account first'); + toast.error('Please connect your Gitlab or Github account first'); + + setIsLoading(false); + return; } @@ -669,23 +663,26 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit data.every((item) => typeof item === 'object' && item !== null && 'full_name' in item) ) { // Add source property to each GitHub repository - const reposWithSource = data.map(repo => ({ + const reposWithSource = data.map((repo) => ({ ...repo, - source: 'github' as any + source: 'github' as any, })); setGithubRepositories(reposWithSource as GitHubRepoInfo[]); } else { throw new Error('Invalid GitHub repository data format'); } } else if (category === 'gitlab') { - // Make sure we have a valid GitLab token if (!gitlabConnection?.token) { toast.error('GitLab token not found. Please connect your GitLab account first.'); + + setShowAuthGitlabDialog(true); + setIsLoading(false); + return; } console.log('Fetching GitLab repositories...'); - + // Use a more reliable API endpoint with better parameters response = await fetch( 'https://gitlab.com/api/v4/projects?membership=true&min_access_level=20&order_by=last_activity_at&per_page=100&simple=true', @@ -700,10 +697,15 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit if (!response.ok) { const errorText = await response.text(); console.error('GitLab API error:', response.status, errorText); - throw new Error(`Failed to fetch GitLab projects: ${response.status} ${response.statusText}`); + toast.error(`Failed to fetch GitLab projects: ${response.status} ${response.statusText}`); + + setShowAuthGitlabDialog(true); + setIsLoading(false); + + return; } - const data = await response.json() as any[]; + const data = (await response.json()) as any[]; console.log('GitLab repositories data:', data.length, 'repositories found'); if ( @@ -722,8 +724,9 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit updated_at: item.last_activity_at || new Date().toISOString(), language: item.language || 'Unknown', languages_url: `https://gitlab.com/api/v4/projects/${item.id}/languages`, + // Add a source property to identify this as a GitLab repository - source: 'gitlab' as any + source: 'gitlab' as any, })); setGitlabRepositories(normalizedData); @@ -733,7 +736,7 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit } } } catch (error) { - console.error('Failed to fecth repositories:', error); + console.error('Failed to fetch repositories:', error); toast.error(`Failed to fetch your ${category} repositories`); } finally { setIsLoading(false); @@ -795,7 +798,7 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit // Determine if this is a GitHub or GitLab repository based on the source property we added const isGitHub = (repo as any).source === 'github'; const isGitLab = (repo as any).source === 'gitlab'; - + const githubConnection = getLocalStorage('github_connection'); const gitlabConnection = getLocalStorage('gitlab_connection'); @@ -836,7 +839,7 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit toast.error('GitLab token not found. Please connect your GitLab account first.'); return; } - + headers = { Accept: 'application/json', Authorization: `Bearer ${gitlabConnection.token}`, @@ -844,12 +847,13 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit // Get the project ID from the repository object const projectId = repo.id; + if (!projectId) { throw new Error('GitLab project ID not found'); } console.log('Fetching branches for GitLab project:', projectId); - + // Fetch branches from GitLab API response = await fetch(`https://gitlab.com/api/v4/projects/${projectId}/repository/branches`, { headers, @@ -867,14 +871,14 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit if (Array.isArray(data) && data.length > 0) { // Get the default branch from the repository object const defaultBranch = (repo as any).default_branch || 'main'; - + setBranches( data.map((branch) => ({ name: branch.name, default: branch.name === defaultBranch, })), ); - + // Set the selected branch to the default branch setSelectedBranch(defaultBranch); } else if (Array.isArray(data) && data.length === 0) { @@ -1228,27 +1232,31 @@ export function RepositorySelectionDialog({ isOpen, onClose, onSelect }: Reposit Import GitHub/Gitlab Repository - -