feat: add SSH URL validation, inline radio buttons in repo creation dialog
RepositoryCreateDialog (already unified, used everywhere): - Add isSshUrl() helper to detect git@ and ssh:// URLs - Require SSH key selection when URL is SSH; show error otherwise - Inline existing/new radio buttons with smaller styling (.repo-mode-radios) Tests: - Update repositories-settings-tab.test.tsx to select SSH key for owner/repo mode - Mock listSSHKeys in tests Quality gates: tsc --noEmit pass, npm run build pass, 80/80 tests pass
This commit is contained in:
@@ -124,6 +124,11 @@ export const RepositoryCreateDialog = ({
|
||||
onClose();
|
||||
};
|
||||
|
||||
const isSshUrl = (url: string): boolean => {
|
||||
const u = url.trim().toLowerCase();
|
||||
return u.startsWith("git@") || u.startsWith("ssh://");
|
||||
};
|
||||
|
||||
const handleSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault();
|
||||
setFormError(null);
|
||||
@@ -140,19 +145,27 @@ export const RepositoryCreateDialog = ({
|
||||
};
|
||||
|
||||
if (createMode === "clone") {
|
||||
let remoteUrl: string;
|
||||
if (useAdvancedUrl) {
|
||||
if (!advancedUrl.trim()) {
|
||||
setFormError("Remote URL is required for advanced cloning");
|
||||
return;
|
||||
}
|
||||
input.remote_url = advancedUrl.trim();
|
||||
remoteUrl = advancedUrl.trim();
|
||||
} else {
|
||||
if (!owner.trim() || !repoName.trim()) {
|
||||
setFormError("Owner and repository name are required");
|
||||
return;
|
||||
}
|
||||
input.remote_url = `git@git.commumedia.org:${owner.trim()}/${repoName.trim()}.git`;
|
||||
remoteUrl = `git@git.commumedia.org:${owner.trim()}/${repoName.trim()}.git`;
|
||||
}
|
||||
|
||||
if (isSshUrl(remoteUrl) && !selectedSshKey) {
|
||||
setFormError("An SSH key is required for SSH URLs");
|
||||
return;
|
||||
}
|
||||
|
||||
input.remote_url = remoteUrl;
|
||||
if (selectedSshKey) {
|
||||
input.ssh_key_id = selectedSshKey;
|
||||
}
|
||||
@@ -202,24 +215,24 @@ export const RepositoryCreateDialog = ({
|
||||
blank bare repo here.
|
||||
</p>
|
||||
<form onSubmit={handleSubmit} className="stack">
|
||||
<div className="form-field">
|
||||
<label>
|
||||
<div className="form-field repo-mode-radios">
|
||||
<label className="repo-mode-label">
|
||||
<input
|
||||
type="radio"
|
||||
name="repository-mode"
|
||||
checked={createMode === "clone"}
|
||||
onChange={() => setCreateMode("clone")}
|
||||
/>
|
||||
Clone existing repository
|
||||
<span>Clone existing</span>
|
||||
</label>
|
||||
<label>
|
||||
<label className="repo-mode-label">
|
||||
<input
|
||||
type="radio"
|
||||
name="repository-mode"
|
||||
checked={createMode === "blank"}
|
||||
onChange={() => setCreateMode("blank")}
|
||||
/>
|
||||
Create blank repository
|
||||
<span>Create blank</span>
|
||||
</label>
|
||||
</div>
|
||||
<label className="form-field">
|
||||
|
||||
Reference in New Issue
Block a user