@graphteon/juricode
Version:
We are forging the future with lines of digital steel
221 lines • 17.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const ink_1 = require("ink");
const open_hands_1 = __importDefault(require("../api/open-hands"));
const CreateTaskTUI = ({ onBack, onTaskCreated }) => {
const [currentStep, setCurrentStep] = (0, react_1.useState)(0);
const [formData, setFormData] = (0, react_1.useState)({
title: '',
message: '',
repository: '',
gitProvider: '',
branch: 'main'
});
const [repositories, setRepositories] = (0, react_1.useState)([]);
const [branches, setBranches] = (0, react_1.useState)([]);
const [selectedRepoIndex, setSelectedRepoIndex] = (0, react_1.useState)(0);
const [selectedBranchIndex, setSelectedBranchIndex] = (0, react_1.useState)(0);
const [currentPage, setCurrentPage] = (0, react_1.useState)(0);
const [loading, setLoading] = (0, react_1.useState)(false);
const [error, setError] = (0, react_1.useState)(null);
const [creating, setCreating] = (0, react_1.useState)(false);
const { exit } = (0, ink_1.useApp)();
const ITEMS_PER_PAGE = 20;
const steps = [
'Enter Task Title',
'Enter Initial Message (Optional)',
'Select Repository',
'Select Branch',
'Review & Create'
];
(0, react_1.useEffect)(() => {
if (currentStep === 2) {
fetchRepositories();
}
}, [currentStep]);
(0, react_1.useEffect)(() => {
if (currentStep === 3 && formData.repository) {
fetchBranches();
}
}, [currentStep, formData.repository]);
const fetchRepositories = async () => {
try {
setLoading(true);
const repos = await open_hands_1.default.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 open_hands_1.default.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 open_hands_1.default.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);
}
};
(0, ink_1.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 ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Enter a title for your task:" }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { children: [formData.title, "\u2588"] }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Press Enter to continue" }) })] }));
case 1:
return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Enter an initial message (optional):" }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { children: [formData.message, "\u2588"] }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.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 ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Select a repository (or skip):" }), loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, justifyContent: "center", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading repositories..." }) })) : error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : repositories.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: selectedRepoIndex === 0 ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: selectedRepoIndex === 0 ? 'green' : 'white', bold: true, children: [selectedRepoIndex === 0 ? '▶ ' : ' ', "\u23ED\uFE0F Skip - Create task without repository"] }) }) }) })) : ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", marginTop: 1, children: [currentPageRepos.map((repo, index) => ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: index === selectedRepoIndex ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: (0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: index === selectedRepoIndex ? 'green' : 'white', bold: true, children: [index === selectedRepoIndex ? '▶ ' : ' ', repo.full_name, repo.stargazers_count && repo.stargazers_count > 0 && ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: [" \u2605", repo.stargazers_count] }))] }) }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Provider: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: repo.git_provider }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: repo.is_public ? 'green' : 'yellow', children: repo.is_public ? 'Public' : 'Private' })] })] }) }) }, repo.full_name))), showSkipOnThisPage && ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: currentPageRepos.length === selectedRepoIndex ? 'green' : 'gray', paddingX: 1, paddingY: 0, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: currentPageRepos.length === selectedRepoIndex ? 'green' : 'white', bold: true, children: [currentPageRepos.length === selectedRepoIndex ? '▶ ' : ' ', "\u23ED\uFE0F Skip - Create task without repository"] }) }) })), totalPages > 1 && ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: ["Page ", currentPage + 1, " of ", totalPages, " \u2022 Showing ", currentPageRepos.length, " of ", repositories.length, " repositories", showSkipOnThisPage && ' + Skip option'] }) }))] }))] }));
case 3:
return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: ["Select a branch for ", formData.repository, ":"] }), loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, justifyContent: "center", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading branches..." }) })) : error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : branches.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No branches found." }) })) : ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", marginTop: 1, children: [branches.slice(0, 5).map((branch, index) => ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: index === selectedBranchIndex ? 'green' : 'white', children: [index === selectedBranchIndex ? '▶ ' : ' ', branch.name, branch.protected && (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "red", children: " \uD83D\uDD12" })] }) }, branch.name))), branches.length > 5 && ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: ["... and ", branches.length - 5, " more"] }))] }))] }));
case 4:
return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Review your task:" }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, paddingY: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Title: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "white", bold: true, children: formData.title })] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Message: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "white", children: formData.message || '(none)' })] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Repository: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "cyan", children: formData.repository || '(none - standalone task)' })] }), formData.repository && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Provider: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: formData.gitProvider })] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Branch: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "green", children: formData.branch })] })] }))] }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: creating ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Creating task..." })) : ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "green", children: "Press Enter to create task" })) })] }));
default:
return null;
}
};
return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", height: "100%", children: [(0, jsx_runtime_1.jsxs)(ink_1.Box, { borderStyle: "single", borderColor: "blue", paddingX: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", bold: true, children: "\uD83D\uDCDD Create New Task" }), (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [" - Step ", currentStep + 1, " of ", steps.length, ": ", steps[currentStep]] })] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: [error && currentStep === 4 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : null, renderStep()] }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsx)(ink_1.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`) }) })] }));
};
exports.default = CreateTaskTUI;
//# sourceMappingURL=CreateTaskTUI.js.map