import { useState, useRef, useEffect } from "react"; import { Edit3, Check, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import type { Repository } from "@/lib/db/schema"; interface InlineDestinationEditorProps { repository: Repository; giteaConfig: any; onUpdate: (repoId: string, newDestination: string | null) => Promise; isUpdating?: boolean; className?: string; } export function InlineDestinationEditor({ repository, giteaConfig, onUpdate, isUpdating = false, className, }: InlineDestinationEditorProps) { const [isEditing, setIsEditing] = useState(false); const [editValue, setEditValue] = useState(""); const [isLoading, setIsLoading] = useState(false); const inputRef = useRef(null); // Determine the default destination based on repository properties and config const getDefaultDestination = () => { // Starred repos always go to the configured starredReposOrg if (repository.isStarred && giteaConfig?.starredReposOrg) { return giteaConfig.starredReposOrg; } // Check mirror strategy const strategy = giteaConfig?.mirrorStrategy || 'preserve'; if (strategy === 'single-org' && giteaConfig?.organization) { // All repos go to a single organization return giteaConfig.organization; } else if (strategy === 'flat-user') { // All repos go under the user account return giteaConfig?.username || repository.owner; } else { // 'preserve' strategy or default // For organization repos, use the organization name if (repository.organization) { return repository.organization; } // For personal repos, check if personalReposOrg is configured (but not in preserve mode) if (!repository.organization && giteaConfig?.personalReposOrg && strategy !== 'preserve') { return giteaConfig.personalReposOrg; } // Default to the gitea username or owner return giteaConfig?.username || repository.owner; } }; const defaultDestination = getDefaultDestination(); const currentDestination = repository.destinationOrg || defaultDestination; const hasOverride = repository.destinationOrg && repository.destinationOrg !== defaultDestination; const isStarredRepo = repository.isStarred && giteaConfig?.starredReposOrg; useEffect(() => { if (isEditing && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [isEditing]); const handleStartEdit = () => { if (isStarredRepo) return; // Don't allow editing starred repos setEditValue(currentDestination); setIsEditing(true); }; const handleSave = async () => { const trimmedValue = editValue.trim(); const newDestination = trimmedValue === defaultDestination ? null : trimmedValue; if (trimmedValue === currentDestination) { setIsEditing(false); return; } setIsLoading(true); try { await onUpdate(repository.id!, newDestination); setIsEditing(false); } catch (error) { // Revert on error setEditValue(currentDestination); } finally { setIsLoading(false); } }; const handleCancel = () => { setEditValue(currentDestination); setIsEditing(false); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter") { e.preventDefault(); handleSave(); } else if (e.key === "Escape") { e.preventDefault(); handleCancel(); } }; if (isEditing) { return (
setEditValue(e.target.value)} onKeyDown={handleKeyDown} onBlur={handleCancel} className="h-6 text-sm px-2 py-0 w-24" disabled={isLoading} />
); } return (
{/* Show GitHub org if exists */} {repository.organization && ( {repository.organization} )} {/* Show Gitea destination */}
{currentDestination || "-"} {hasOverride && ( custom )} {isStarredRepo && ( starred )} {!isStarredRepo && ( )}
); }