Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev

This commit is contained in:
Fusion
2026-05-24 12:06:38 +02:00
7 changed files with 510 additions and 15 deletions
+127 -12
View File
@@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { Icon } from "./icon";
import { createInstance, startInstance, type ToolInstance } from "../api/sessions";
import type { Project } from "../types";
import type { GitRepository } from "../api/git_repositories";
import { listRepositoryBranches, type GitRepository, type Branch } from "../api/git_repositories";
import type { ToolType } from "../api/tool_types";
import { listSSHKeys, type SSHKey } from "../api/ssh_keys";
@@ -47,6 +47,12 @@ export const CreateSessionForm = ({
const [branch, setBranch] = useState("main");
const [sshKeys, setSshKeys] = useState<SSHKey[]>([]);
const [branches, setBranches] = useState<Branch[]>([]);
const [isLoadingBranches, setIsLoadingBranches] = useState(false);
const [isCreatingNewBranch, setIsCreatingNewBranch] = useState(false);
const [newBranchName, setNewBranchName] = useState("");
const [baseBranch, setBaseBranch] = useState("");
const [status, setStatus] = useState<"idle" | "creating" | "error">("idle");
const [progress, setProgress] = useState("");
const [error, setError] = useState<string | null>(null);
@@ -65,6 +71,31 @@ export const CreateSessionForm = ({
void loadKeys();
}, [showCloneMode]);
// Load branches when selected repo changes
useEffect(() => {
if (!selectedRepo || !showCloneMode) {
setBranches([]);
return;
}
const loadBranches = async () => {
setIsLoadingBranches(true);
try {
const branchList = await listRepositoryBranches(selectedRepo);
setBranches(branchList);
const defaultBranch = branchList.find((b) => b.is_default);
if (defaultBranch) {
setBranch(defaultBranch.name);
setBaseBranch(defaultBranch.name);
}
} catch {
// ignore
} finally {
setIsLoadingBranches(false);
}
};
void loadBranches();
}, [selectedRepo, showCloneMode]);
// Filter repositories by selected project
const availableRepos = selectedProject
? repositories.filter((r) => r.project_id === selectedProject)
@@ -100,7 +131,14 @@ export const CreateSessionForm = ({
selectedToolType,
displayName || undefined,
showCloneMode ? cloneMode : undefined,
showCloneMode && cloneMode === "clone" ? branch : undefined
showCloneMode && cloneMode === "clone"
? isCreatingNewBranch
? baseBranch
: branch
: undefined,
showCloneMode && cloneMode === "clone" && isCreatingNewBranch
? newBranchName
: undefined
);
setProgress("Starting container...");
@@ -113,6 +151,10 @@ export const CreateSessionForm = ({
setDisplayName("");
setCloneMode("mount");
setBranch("main");
setIsCreatingNewBranch(false);
setNewBranchName("");
setBaseBranch("");
setBranches([]);
setStatus("idle");
onSuccess?.(instance);
@@ -247,16 +289,89 @@ export const CreateSessionForm = ({
</label>
{cloneMode === "clone" && (
<label className="form-field">
Branch
<input
type="text"
value={branch}
onChange={(e) => setBranch(e.target.value)}
placeholder="main"
disabled={isSubmitting}
/>
</label>
<>
<label className="form-field">
Branch
{isLoadingBranches ? (
<span className="muted">Loading branches...</span>
) : (
<select
value={isCreatingNewBranch ? "__new__" : branch}
onChange={(e) => {
const value = e.target.value;
if (value === "__new__") {
setIsCreatingNewBranch(true);
setNewBranchName("");
} else {
setIsCreatingNewBranch(false);
setBranch(value);
setBaseBranch(value);
}
}}
disabled={isSubmitting}
>
{branches.map((b) => (
<option key={b.name} value={b.name}>
{b.name} {b.is_default ? "(default)" : ""}
</option>
))}
<option value="__new__">Create new branch...</option>
</select>
)}
</label>
{isCreatingNewBranch && (
<>
<label className="form-field">
New Branch Name
<input
type="text"
value={newBranchName}
onChange={(e) => setNewBranchName(e.target.value)}
placeholder="feature/my-new-branch"
required
disabled={isSubmitting}
/>
</label>
<label className="form-field">
Base Branch
<select
value={baseBranch}
onChange={(e) => setBaseBranch(e.target.value)}
disabled={isSubmitting}
>
{branches.map((b) => (
<option key={b.name} value={b.name}>
{b.name} {b.is_default ? "(default)" : ""}
</option>
))}
</select>
</label>
</>
)}
{selectedRepo && (
<div className="form-field ssh-key-info">
{(() => {
const repo = repositories.find((r) => r.id === selectedRepo);
if (!repo) return null;
if (repo.ssh_key_id) {
const key = sshKeys.find((k) => k.id === repo.ssh_key_id);
return (
<span className="success-text">
SSH key: {key?.name || "Assigned"}
</span>
);
}
return (
<span className="warning-text">
No SSH key assigned to this repository. Clone mode requires an SSH key.
</span>
);
})()}
</div>
)}
</>
)}
</div>
)}