UNPKG

@graphteon/juricode

Version:

We are forging the future with lines of digital steel

216 lines 14.9 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import React, { useState, useEffect } from 'react'; import { Box, Text, useInput, useApp } from 'ink'; import OpenHands from '../api/open-hands'; const CreateTaskTUI = ({ onBack, onTaskCreated }) => { const [currentStep, setCurrentStep] = useState(0); const [formData, setFormData] = useState({ title: '', message: '', repository: '', gitProvider: '', branch: 'main' }); const [repositories, setRepositories] = useState([]); const [branches, setBranches] = useState([]); const [selectedRepoIndex, setSelectedRepoIndex] = useState(0); const [selectedBranchIndex, setSelectedBranchIndex] = useState(0); const [currentPage, setCurrentPage] = useState(0); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [creating, setCreating] = useState(false); const { exit } = useApp(); const ITEMS_PER_PAGE = 20; const steps = [ 'Enter Task Title', 'Enter Initial Message (Optional)', 'Select Repository', 'Select Branch', 'Review & Create' ]; useEffect(() => { if (currentStep === 2) { fetchRepositories(); } }, [currentStep]); useEffect(() => { if (currentStep === 3 && formData.repository) { fetchBranches(); } }, [currentStep, formData.repository]); const fetchRepositories = async () => { try { setLoading(true); const repos = await OpenHands.retrieveUserGitRepositories(); setRepositories(repos); setSelectedRepoIndex(0); setCurrentPage(0); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch repositories'); } finally { setLoading(false); } }; const fetchBranches = async () => { try { setLoading(true); const repoBranches = await OpenHands.getRepositoryBranches(formData.repository); setBranches(repoBranches); setSelectedBranchIndex(0); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch branches'); } finally { setLoading(false); } }; const createTask = async () => { try { setCreating(true); const conversation = await OpenHands.createConversation(formData.repository || undefined, formData.gitProvider || undefined, formData.message || undefined, [], undefined, formData.repository ? formData.branch : undefined); onTaskCreated(conversation.conversation_id); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create task'); } finally { setCreating(false); } }; useInput((input, key) => { if (key.escape) { if (currentStep > 0) { setCurrentStep(currentStep - 1); return; } onBack(); return; } if (loading || creating) return; if (currentStep === 0) { if (key.return && formData.title.trim()) { setCurrentStep(1); return; } if (key.backspace || key.delete) { setFormData(prev => ({ ...prev, title: prev.title.slice(0, -1) })); return; } if (input && input.length === 1) { setFormData(prev => ({ ...prev, title: prev.title + input })); return; } } if (currentStep === 1) { if (key.return) { setCurrentStep(2); return; } if (key.backspace || key.delete) { setFormData(prev => ({ ...prev, message: prev.message.slice(0, -1) })); return; } if (input && input.length === 1) { setFormData(prev => ({ ...prev, message: prev.message + input })); return; } } if (currentStep === 2) { const totalItems = repositories.length + 1; const startIndex = currentPage * ITEMS_PER_PAGE; const endIndex = Math.min(startIndex + ITEMS_PER_PAGE, totalItems); const itemsOnCurrentPage = endIndex - startIndex; if (key.upArrow && selectedRepoIndex > 0) { setSelectedRepoIndex(selectedRepoIndex - 1); } if (key.downArrow && selectedRepoIndex < itemsOnCurrentPage - 1) { setSelectedRepoIndex(selectedRepoIndex + 1); } if (key.leftArrow && currentPage > 0) { setCurrentPage(currentPage - 1); setSelectedRepoIndex(0); } if (key.rightArrow && endIndex < totalItems) { setCurrentPage(currentPage + 1); setSelectedRepoIndex(0); } if (key.return) { const actualIndex = startIndex + selectedRepoIndex; if (actualIndex === repositories.length) { setFormData(prev => ({ ...prev, repository: '', gitProvider: '', branch: 'main' })); setCurrentStep(4); return; } if (actualIndex < repositories.length) { const selectedRepo = repositories[actualIndex]; setFormData(prev => ({ ...prev, repository: selectedRepo.full_name, gitProvider: selectedRepo.git_provider })); setCurrentStep(3); return; } } } if (currentStep === 3) { if (key.upArrow && selectedBranchIndex > 0) { setSelectedBranchIndex(selectedBranchIndex - 1); } if (key.downArrow && selectedBranchIndex < branches.length - 1) { setSelectedBranchIndex(selectedBranchIndex + 1); } if (key.return && branches.length > 0) { const selectedBranch = branches[selectedBranchIndex]; setFormData(prev => ({ ...prev, branch: selectedBranch.name })); setCurrentStep(4); return; } } if (currentStep === 4) { if (key.return) { createTask(); return; } } if (input === 'q') { exit(); } }); const renderStep = () => { switch (currentStep) { case 0: return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "Enter a title for your task:" }), _jsx(Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: _jsxs(Text, { children: [formData.title, "\u2588"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press Enter to continue" }) })] })); case 1: return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "Enter an initial message (optional):" }), _jsx(Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: _jsxs(Text, { children: [formData.message, "\u2588"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "Press Enter to continue (can be empty)" }) })] })); case 2: const totalItems = repositories.length + 1; const startIndex = currentPage * ITEMS_PER_PAGE; const endIndex = Math.min(startIndex + ITEMS_PER_PAGE, totalItems); const totalPages = Math.ceil(totalItems / ITEMS_PER_PAGE); const currentPageRepos = repositories.slice(startIndex, Math.min(startIndex + ITEMS_PER_PAGE, repositories.length)); const showSkipOnThisPage = startIndex + ITEMS_PER_PAGE >= repositories.length; return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "Select a repository (or skip):" }), loading ? (_jsx(Box, { marginTop: 1, justifyContent: "center", children: _jsx(Text, { color: "yellow", children: "\u23F3 Loading repositories..." }) })) : error ? (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u274C Error: ", error] }) })) : repositories.length === 0 ? (_jsx(Box, { marginTop: 1, children: _jsx(Box, { marginBottom: 1, children: _jsx(Box, { borderStyle: "single", borderColor: selectedRepoIndex === 0 ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: _jsxs(Text, { color: selectedRepoIndex === 0 ? 'green' : 'white', bold: true, children: [selectedRepoIndex === 0 ? '▶ ' : ' ', "\u23ED\uFE0F Skip - Create task without repository"] }) }) }) })) : (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [currentPageRepos.map((repo, index) => (_jsx(Box, { marginBottom: 1, children: _jsx(Box, { borderStyle: "single", borderColor: index === selectedRepoIndex ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: index === selectedRepoIndex ? 'green' : 'white', bold: true, children: [index === selectedRepoIndex ? '▶ ' : ' ', repo.full_name, repo.stargazers_count && repo.stargazers_count > 0 && (_jsxs(Text, { color: "yellow", children: [" \u2605", repo.stargazers_count] }))] }) }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Provider: " }), _jsx(Text, { color: "blue", children: repo.git_provider }), _jsx(Text, { color: "gray", children: " | " }), _jsx(Text, { color: repo.is_public ? 'green' : 'yellow', children: repo.is_public ? 'Public' : 'Private' })] })] }) }) }, repo.full_name))), showSkipOnThisPage && (_jsx(Box, { marginBottom: 1, children: _jsx(Box, { borderStyle: "single", borderColor: currentPageRepos.length === selectedRepoIndex ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: _jsxs(Text, { color: currentPageRepos.length === selectedRepoIndex ? 'green' : 'white', bold: true, children: [currentPageRepos.length === selectedRepoIndex ? '▶ ' : ' ', "\u23ED\uFE0F Skip - Create task without repository"] }) }) })), totalPages > 1 && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["Page ", currentPage + 1, " of ", totalPages, " \u2022 Showing ", currentPageRepos.length, " of ", repositories.length, " repositories", showSkipOnThisPage && ' + Skip option'] }) }))] }))] })); case 3: return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "yellow", children: ["Select a branch for ", formData.repository, ":"] }), loading ? (_jsx(Box, { marginTop: 1, justifyContent: "center", children: _jsx(Text, { color: "yellow", children: "\u23F3 Loading branches..." }) })) : error ? (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u274C Error: ", error] }) })) : branches.length === 0 ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "No branches found." }) })) : (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [branches.slice(0, 5).map((branch, index) => (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: index === selectedBranchIndex ? 'green' : 'white', children: [index === selectedBranchIndex ? '▶ ' : ' ', branch.name, branch.protected && _jsx(Text, { color: "red", children: " \uD83D\uDD12" })] }) }, branch.name))), branches.length > 5 && (_jsxs(Text, { color: "gray", children: ["... and ", branches.length - 5, " more"] }))] }))] })); case 4: return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "yellow", children: "Review your task:" }), _jsx(Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, paddingY: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: "Title: " }), _jsx(Text, { color: "white", bold: true, children: formData.title })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Message: " }), _jsx(Text, { color: "white", children: formData.message || '(none)' })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Repository: " }), _jsx(Text, { color: "cyan", children: formData.repository || '(none - standalone task)' })] }), formData.repository && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Provider: " }), _jsx(Text, { color: "blue", children: formData.gitProvider })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Branch: " }), _jsx(Text, { color: "green", children: formData.branch })] })] }))] }) }), _jsx(Box, { marginTop: 1, children: creating ? (_jsx(Text, { color: "yellow", children: "\u23F3 Creating task..." })) : (_jsx(Text, { color: "green", children: "Press Enter to create task" })) })] })); default: return null; } }; return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsxs(Box, { borderStyle: "single", borderColor: "blue", paddingX: 1, children: [_jsx(Text, { color: "blue", bold: true, children: "\uD83D\uDCDD Create New Task" }), _jsxs(Text, { color: "gray", children: [" - Step ", currentStep + 1, " of ", steps.length, ": ", steps[currentStep]] })] }), _jsxs(Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: [error && currentStep === 4 ? (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "red", children: ["\u274C Error: ", error] }) })) : null, renderStep()] }), _jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: _jsx(Text, { color: "gray", children: currentStep === 2 && repositories.length > 0 ? (`↑↓ Navigate • ${Math.ceil((repositories.length + 1) / ITEMS_PER_PAGE) > 1 ? '←→ Page • ' : ''}Enter Select • ${currentStep > 0 ? 'ESC Previous Step • ' : 'ESC Back • '}Q Quit`) : currentStep === 3 && branches.length > 0 ? (`↑↓ Navigate • Enter Select • ${currentStep > 0 ? 'ESC Previous Step • ' : 'ESC Back • '}Q Quit`) : (`${currentStep > 0 ? 'ESC Previous Step • ' : 'ESC Back • '}Q Quit`) }) })] })); }; export default CreateTaskTUI; //# sourceMappingURL=CreateTaskTUI.js.map