fix: clone selected branch - [INS-1462] (#9408)

* fix: clone selected branch

* fix: delete unuse git-related modal

* fix: support gitlab & azure

* fix: remove unuse entry
This commit is contained in:
Curry Yang
2025-12-10 04:26:49 +01:00
committed by GitHub
parent dfcb8ebace
commit f42923d469
10 changed files with 7 additions and 305 deletions

View File

@@ -15,6 +15,7 @@ interface CloneGitRepoData {
email: string;
};
credentials: GitCredentials;
ref: string;
}
export async function clientAction({ request }: Route.ClientActionArgs) {

View File

@@ -69,7 +69,6 @@ import { ProjectDropdown } from '~/ui/components/dropdowns/project-dropdown';
import { WorkspaceCardDropdown } from '~/ui/components/dropdowns/workspace-card-dropdown';
import { ErrorBoundary } from '~/ui/components/error-boundary';
import { Icon } from '~/ui/components/icon';
import { GitRepositoryCloneModal } from '~/ui/components/modals/git-repository-settings-modal/git-repo-clone-modal';
import { ImportModal } from '~/ui/components/modals/import-modal/import-modal';
import { NewWorkspaceModal } from '~/ui/components/modals/new-workspace-modal';
import { ProjectModal } from '~/ui/components/modals/project-modal';
@@ -637,8 +636,6 @@ const Component = () => {
};
});
const [isGitRepositoryCloneModalOpen, setIsGitRepositoryCloneModalOpen] = useState(false);
const navigate = useNavigate();
const [newWorkspaceModalState, setNewWorkspaceModalState] = useState<{
@@ -1330,10 +1327,6 @@ const Component = () => {
)}
</Panel>
</PanelGroup>
{isGitRepositoryCloneModalOpen && (
<GitRepositoryCloneModal onHide={() => setIsGitRepositoryCloneModalOpen(false)} />
)}
{isNewProjectModalOpen && (
<ProjectModal
isOpen={isNewProjectModalOpen}

View File

@@ -70,7 +70,6 @@ import { ProjectDropdown } from '~/ui/components/dropdowns/project-dropdown';
import { WorkspaceCardDropdown } from '~/ui/components/dropdowns/workspace-card-dropdown';
import { ErrorBoundary } from '~/ui/components/error-boundary';
import { Icon } from '~/ui/components/icon';
import { GitRepositoryCloneModal } from '~/ui/components/modals/git-repository-settings-modal/git-repo-clone-modal';
import { ImportModal } from '~/ui/components/modals/import-modal/import-modal';
import { NewWorkspaceModal } from '~/ui/components/modals/new-workspace-modal';
import { ProjectModal } from '~/ui/components/modals/project-modal';
@@ -621,8 +620,6 @@ const Component = () => {
};
});
const [isGitRepositoryCloneModalOpen, setIsGitRepositoryCloneModalOpen] = useState(false);
const navigate = useNavigate();
const [newWorkspaceModalState, setNewWorkspaceModalState] = useState<{
@@ -1295,10 +1292,6 @@ const Component = () => {
)}
</Panel>
</PanelGroup>
{isGitRepositoryCloneModalOpen && (
<GitRepositoryCloneModal onHide={() => setIsGitRepositoryCloneModalOpen(false)} />
)}
{isNewProjectModalOpen && (
<ProjectModal
isOpen={isNewProjectModalOpen}

View File

@@ -29,6 +29,7 @@ export interface CreateProjectData {
token?: string;
oauth2format?: OauthProviderName;
connectRepositoryLater?: boolean;
ref?: string;
}
export const reportGitProjectCount = async (organizationId: string, sessionId: string, maxRetries = 3) => {
@@ -117,6 +118,7 @@ export const createProject = async (organizationId: string, newProjectData: Crea
username: '',
password: '',
},
ref: newProjectData.ref || '',
});
if (errors) {

View File

@@ -27,7 +27,6 @@ import {
import type { Project } from '../../../models/project';
import type { Workspace } from '../../../models/workspace';
import { Icon } from '../icon';
import { GitRepositorySettingsModal } from '../modals/git-repository-settings-modal';
import { SyncBranchesModal } from '../modals/sync-branches-modal';
import { SyncHistoryModal } from '../modals/sync-history-modal';
import { SyncStagingModal } from '../modals/sync-staging-modal';
@@ -48,7 +47,6 @@ export const SyncDropdown: FC<Props> = () => {
workspaceId: string;
};
const [isGitRepoSettingsModalOpen, setIsGitRepoSettingsModalOpen] = useState(false);
const [isSyncHistoryModalOpen, setIsSyncHistoryModalOpen] = useState(false);
const [isSyncStagingModalOpen, setIsSyncStagingModalOpen] = useState(false);
const [isSyncBranchesModalOpen, setIsSyncBranchesModalOpen] = useState(false);
@@ -453,7 +451,6 @@ export const SyncDropdown: FC<Props> = () => {
</Menu>
</Popover>
</MenuTrigger>
{isGitRepoSettingsModalOpen && <GitRepositorySettingsModal onHide={() => setIsGitRepoSettingsModalOpen(false)} />}
{isSyncBranchesModalOpen && (
<SyncBranchesModal
branches={localBranches}

View File

@@ -9,7 +9,7 @@ import { GitRemoteBranchSelect } from './git-remote-branch-select';
export interface Props {
gitRepository?: Partial<GitRepository> | null;
onSubmit: (args: Partial<GitRepository>) => void;
onSubmit: (args: Partial<GitRepository & { ref?: string }>) => void;
}
export const CustomRepositorySettingsFormGroup: FunctionComponent<Props> = ({ gitRepository, onSubmit }) => {
@@ -41,6 +41,7 @@ export const CustomRepositorySettingsFormGroup: FunctionComponent<Props> = ({ gi
const formData = new FormData(event.currentTarget);
onSubmit({
uri: (formData.get('uri') as string) || '',
ref: (formData.get('branch') as string) || '',
credentials: {
username: (formData.get('username') as string) || '',
password: (formData.get('password') as string) || '',

View File

@@ -66,7 +66,7 @@ const Avatar = ({ src }: { src: string }) => {
interface GitLabRepositoryFormProps {
uri?: string;
onSubmit: (args: Partial<GitRepository>) => void;
onSubmit: (args: Partial<GitRepository & { ref?: string }>) => void;
credentials: GitCredentials;
}
@@ -83,6 +83,7 @@ const GitLabRepositoryForm = ({ uri, credentials, onSubmit }: GitLabRepositoryFo
event.preventDefault();
onSubmit({
uri: (new FormData(event.currentTarget).get('uri') as string) ?? '',
ref: (new FormData(event.currentTarget).get('branch') as string) ?? '',
author: {
name: credentials.author.name,
email: credentials.author.email,

View File

@@ -1,142 +0,0 @@
import React, { useEffect, useRef, useState } from 'react';
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
import { useParams } from 'react-router';
import { useGitCloneActionFetcher } from '~/routes/git.clone';
import { docsGitSync } from '../../../../common/documentation';
import type { GitRepository, OauthProviderName } from '../../../../models/git-repository';
import { Link } from '../../base/link';
import { Modal, type ModalHandle, type ModalProps } from '../../base/modal';
import { ModalBody } from '../../base/modal-body';
import { ModalFooter } from '../../base/modal-footer';
import { ModalHeader } from '../../base/modal-header';
import { ErrorBoundary } from '../../error-boundary';
import { CustomRepositorySettingsFormGroup } from '../../git-credentials/custom-repository-settings-form';
import { GitHubRepositorySetupFormGroup } from '../../git-credentials/github-repository-settings-form';
import { GitLabRepositorySetupFormGroup } from '../../git-credentials/gitlab-repository-settings-form';
import { HelpTooltip } from '../../help-tooltip';
import { showModal } from '..';
import { AlertModal } from '../alert-modal';
export const GitProjectRepositoryCloneModal = (props: ModalProps) => {
const { organizationId } = useParams() as { organizationId: string };
const modalRef = useRef<ModalHandle>(null);
const cloneGitRepositoryFetcher = useGitCloneActionFetcher();
const [selectedTab, setTab] = useState<OauthProviderName>('github');
useEffect(() => {
modalRef.current?.show();
}, []);
const onSubmit = (gitRepositoryPatch: Partial<GitRepository>) => {
const { author, credentials, uri } = gitRepositoryPatch;
cloneGitRepositoryFetcher.submit({
organizationId,
uri: uri || '',
author: {
name: author?.name || '',
email: author?.email || '',
},
credentials: credentials || {
username: '',
password: '',
},
});
};
const isSubmitting = cloneGitRepositoryFetcher.state === 'submitting';
const errors = cloneGitRepositoryFetcher.data?.errors as (Error | string)[];
useEffect(() => {
if (errors && errors.length) {
const errorMessage = errors.map(e => (e instanceof Error ? e.message : typeof e === 'string' && e)).join(', ');
showModal(AlertModal, {
title: 'Error Cloning Repository',
message: errorMessage,
});
}
}, [errors]);
return (
<Modal ref={modalRef} {...props}>
<ModalHeader>
Clone Repository{' '}
<HelpTooltip>
Sync and collaborate with Git
<br />
<Link href={docsGitSync}>Documentation {<i className="fa fa-external-link-square" />}</Link>
</HelpTooltip>
</ModalHeader>
<ModalBody>
<ErrorBoundary>
<Tabs
selectedKey={selectedTab}
onSelectionChange={key => {
setTab(key as OauthProviderName);
}}
aria-label="Git repository settings tabs"
className="flex h-full w-full flex-1 flex-col"
>
<TabList
className="flex h-(--line-height-sm) w-full shrink-0 items-center overflow-x-auto border-b border-solid border-b-(--hl-md) bg-(--color-bg)"
aria-label="Request pane tabs"
>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="github"
>
<div className="flex items-center gap-2">
<i className="fa fa-github" /> GitHub
</div>
</Tab>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="gitlab"
>
<div className="flex items-center gap-2">
<i className="fa fa-gitlab" /> GitLab
</div>
</Tab>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="custom"
>
<div className="flex items-center gap-2">
<i className="fa fa-code-fork" /> Git
</div>
</Tab>
</TabList>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="github">
<GitHubRepositorySetupFormGroup onSubmit={onSubmit} />
</TabPanel>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="gitlab">
<GitLabRepositorySetupFormGroup onSubmit={onSubmit} />
</TabPanel>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="custom">
<CustomRepositorySettingsFormGroup onSubmit={onSubmit} />
</TabPanel>
</Tabs>
</ErrorBoundary>
</ModalBody>
<ModalFooter>
<div>
<button className="btn" onClick={() => modalRef.current?.hide()}>
Cancel
</button>
<button
type="submit"
disabled={isSubmitting}
form={selectedTab}
className="btn"
data-testid="git-repository-settings-modal__sync-btn"
>
Clone
</button>
</div>
</ModalFooter>
</Modal>
);
};

View File

@@ -1,143 +0,0 @@
import React, { useEffect, useRef, useState } from 'react';
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
import { useParams } from 'react-router';
import { useGitCloneActionFetcher } from '~/routes/git.clone';
import { docsGitSync } from '../../../../common/documentation';
import type { GitRepository, OauthProviderName } from '../../../../models/git-repository';
import { Link } from '../../base/link';
import { Modal, type ModalHandle, type ModalProps } from '../../base/modal';
import { ModalBody } from '../../base/modal-body';
import { ModalFooter } from '../../base/modal-footer';
import { ModalHeader } from '../../base/modal-header';
import { ErrorBoundary } from '../../error-boundary';
import { CustomRepositorySettingsFormGroup } from '../../git-credentials/custom-repository-settings-form';
import { GitHubRepositorySetupFormGroup } from '../../git-credentials/github-repository-settings-form';
import { GitLabRepositorySetupFormGroup } from '../../git-credentials/gitlab-repository-settings-form';
import { HelpTooltip } from '../../help-tooltip';
import { showModal } from '..';
import { AlertModal } from '../alert-modal';
export const GitRepositoryCloneModal = (props: ModalProps) => {
const { organizationId, projectId } = useParams() as { organizationId: string; projectId: string };
const modalRef = useRef<ModalHandle>(null);
const cloneGitRepositoryFetcher = useGitCloneActionFetcher();
const [selectedTab, setTab] = useState<OauthProviderName>('github');
useEffect(() => {
modalRef.current?.show();
}, []);
const onSubmit = (gitRepositoryPatch: Partial<GitRepository>) => {
const { author, credentials, uri } = gitRepositoryPatch;
cloneGitRepositoryFetcher.submit({
organizationId,
projectId,
uri: uri || '',
author: {
name: author?.name || '',
email: author?.email || '',
},
credentials: credentials || {
username: '',
password: '',
},
});
};
const isSubmitting = cloneGitRepositoryFetcher.state === 'submitting';
const errors = cloneGitRepositoryFetcher.data?.errors as (Error | string)[];
useEffect(() => {
if (errors && errors.length) {
const errorMessage = errors.map(e => (e instanceof Error ? e.message : typeof e === 'string' && e)).join(', ');
showModal(AlertModal, {
title: 'Error Cloning Repository',
message: errorMessage,
});
}
}, [errors]);
return (
<Modal ref={modalRef} {...props}>
<ModalHeader>
Clone Repository{' '}
<HelpTooltip>
Sync and collaborate with Git
<br />
<Link href={docsGitSync}>Documentation {<i className="fa fa-external-link-square" />}</Link>
</HelpTooltip>
</ModalHeader>
<ModalBody>
<ErrorBoundary>
<Tabs
selectedKey={selectedTab}
onSelectionChange={key => {
setTab(key as OauthProviderName);
}}
aria-label="Git repository settings tabs"
className="flex h-full w-full flex-1 flex-col"
>
<TabList
className="flex h-(--line-height-sm) w-full shrink-0 items-center overflow-x-auto border-b border-solid border-b-(--hl-md) bg-(--color-bg)"
aria-label="Request pane tabs"
>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="github"
>
<div className="flex items-center gap-2">
<i className="fa fa-github" /> GitHub
</div>
</Tab>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="gitlab"
>
<div className="flex items-center gap-2">
<i className="fa fa-gitlab" /> GitLab
</div>
</Tab>
<Tab
className="flex h-full shrink-0 cursor-pointer items-center justify-between gap-2 px-3 py-1 text-(--hl) outline-hidden transition-colors duration-300 select-none hover:bg-(--hl-sm) hover:text-(--color-font) focus:bg-(--hl-sm) aria-selected:bg-(--hl-xs) aria-selected:text-(--color-font) aria-selected:hover:bg-(--hl-sm) aria-selected:focus:bg-(--hl-sm)"
id="custom"
>
<div className="flex items-center gap-2">
<i className="fa fa-code-fork" /> Git
</div>
</Tab>
</TabList>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="github">
<GitHubRepositorySetupFormGroup onSubmit={onSubmit} />
</TabPanel>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="gitlab">
<GitLabRepositorySetupFormGroup onSubmit={onSubmit} />
</TabPanel>
<TabPanel className="h-full w-full overflow-y-auto py-2" id="custom">
<CustomRepositorySettingsFormGroup onSubmit={onSubmit} />
</TabPanel>
</Tabs>
</ErrorBoundary>
</ModalBody>
<ModalFooter>
<div>
<button className="btn" onClick={() => modalRef.current?.hide()}>
Cancel
</button>
<button
type="submit"
disabled={isSubmitting}
form={selectedTab}
className="btn"
data-testid="git-repository-settings-modal__sync-btn"
>
Clone
</button>
</div>
</ModalFooter>
</Modal>
);
};

View File

@@ -1,3 +1,2 @@
export { GitRepositorySettingsModal } from './git-repository-settings-modal';
export { GitProjectRepositorySettingsModal } from './git-project-repository-settings-modal';
export { GitProjectRepositoryCloneModal } from './git-project-repo-clone-modal';