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:
Developer
2026-06-09 09:54:24 +00:00
parent 349066bcfa
commit 152f87a254
3 changed files with 55 additions and 7 deletions
@@ -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">