Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add checkbox to add GitHub issues to the prompt. #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add checkbox to add GitHub issues to the prompt.
This PR extends the UI with a button that appends GitHub issues and comments to the prompt.  Credit for idea: @tomhennigan. Code mostly written by Gemini.
  • Loading branch information
albanie committed Feb 10, 2025
commit fc44f227a326513de510694803c079e35994ffb1
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ <h1 class="text-3xl font-bold mb-2 text-center text-gray-600">GitHub to Plain Te
<i data-lucide="file-text" class="w-5 h-5 mr-2"></i>
Generate Text File
</button>
<button id="fetchIssuesButton" class="flex-1 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline hidden flex items-center justify-center">
<i data-lucide="list" class="w-5 h-5 mr-2"></i>
Add GitHub Issues To Prompt
</button>
<button id="downloadZipButton" class="flex-1 bg-purple-500 hover:bg-purple-600 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline hidden flex items-center justify-center">
<i data-lucide="download" class="w-5 h-5 mr-2"></i>
Download Zip
Expand Down
67 changes: 66 additions & 1 deletion js/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { displayDirectoryStructure, getSelectedFiles, formatRepoContents } from './utils.js';
import { displayDirectoryStructure, getSelectedFiles, formatRepoContents, formatIssues } from './utils.js';

// Load saved token on page load
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
setupShowMoreInfoButton();
loadSavedToken();
setupFetchIssuesButton();
});

// Load saved token from local storage
Expand Down Expand Up @@ -61,6 +62,7 @@ document.getElementById('repoForm').addEventListener('submit', async function (e
displayDirectoryStructure(tree);
document.getElementById('generateTextButton').style.display = 'flex';
document.getElementById('downloadZipButton').style.display = 'flex';
document.getElementById('fetchIssuesButton').style.display = 'flex';
} catch (error) {
outputText.value = `Error fetching repository contents: ${error.message}\n\n` +
"Please ensure:\n" +
Expand All @@ -71,6 +73,69 @@ document.getElementById('repoForm').addEventListener('submit', async function (e
}
});

// Fetch GitHub Issues
async function fetchIssues(owner, repo, token) {
const headers = {
'Accept': 'application/vnd.github+json'
};
if (token) {
headers['Authorization'] = `token ${token}`;
}

let allIssues = [];
let page = 1;
let hasNextPage = true;

while (hasNextPage) {
const url = `https://api.github.com/repos/${owner}/${repo}/issues?state=all&page=${page}&per_page=100`;
const response = await fetch(url, { headers });

if (!response.ok) {
handleFetchError(response);
}

const issues = await response.json();
allIssues = allIssues.concat(issues);

const linkHeader = response.headers.get('Link');
hasNextPage = linkHeader && linkHeader.includes('rel="next"');
page++;
}

return allIssues;
}

// Setup event listener for the Fetch Issues button
function setupFetchIssuesButton() {
const fetchIssuesButton = document.getElementById('fetchIssuesButton');
fetchIssuesButton.addEventListener('click', async function() {
const repoUrl = document.getElementById('repoUrl').value;
const accessToken = document.getElementById('accessToken').value;
const outputText = document.getElementById('outputText');

try {
const { owner, repo } = parseRepoUrl(repoUrl);
const issues = await fetchIssues(owner, repo, accessToken);

if(issues && issues.length >0){
const formattedIssues = formatIssues(issues);
outputText.value += `\n\n--- START OF ISSUES ---\n\n${formattedIssues}\n\n--- END OF ISSUES ---\n`;
}else{
outputText.value += `\n\n--- START OF ISSUES ---\n\nNo issues found for this repository.\n\n--- END OF ISSUES ---\n`;
}

lucide.createIcons(); // Update the icons after modifying the DOM
} catch (error) {
outputText.value = `Error fetching issues: ${error.message}\n\n` +
"Please ensure:\n" +
"1. The repository URL is correct and accessible.\n" +
"2. You have the necessary permissions to access the repository.\n" +
"3. If it's a private repository, you've provided a valid access token.\n" +
"4. There are issues on this repository"
}
});
}

// Event listener for generating text file
document.getElementById('generateTextButton').addEventListener('click', async function () {
const accessToken = document.getElementById('accessToken').value;
Expand Down
53 changes: 52 additions & 1 deletion js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,4 +312,55 @@ function formatRepoContents(contents) {
return formattedText;
}

export { displayDirectoryStructure, sortContents, getSelectedFiles, formatRepoContents };
function formatIssues(issues) {
if (!issues || issues.length === 0) {
return "No issues found.";
}

let formattedText = '';
issues.forEach(issue => {
formattedText += `Issue #${issue.number}:\n`;
formattedText += ` Title: ${issue.title}\n`;
formattedText += ` State: ${issue.state}\n`;
formattedText += ` Author: ${issue.user.login}\n`;
formattedText += ` Created At: ${new Date(issue.created_at).toLocaleString()}\n`;
formattedText += ` Updated At: ${new Date(issue.updated_at).toLocaleString()}\n`;

// Handle labels
if (issue.labels && issue.labels.length > 0) {
formattedText += ` Labels: ${issue.labels.map(label => label.name).join(', ')}\n`;
} else {
formattedText += ` Labels: None\n`;
}

// Handle assignees
if (issue.assignees && issue.assignees.length > 0) {
formattedText += ` Assignees: ${issue.assignees.map(assignee => assignee.login).join(', ')}\n`;
} else {
formattedText += ` Assignees: None\n`;
}
//Handle milestone
if (issue.milestone && issue.milestone.title){
formattedText += ` Milestone: ${issue.milestone.title}\n`;
}else{
formattedText += ` Milestone: none\n`;
}

// Truncate body
const maxBodyLength = 500;
let body = issue.body || "No description provided.";
if (body.length > maxBodyLength) {
body = body.substring(0, maxBodyLength) + "...\n[Truncated for brevity. See full text on GitHub.]";
}
formattedText += ` Body: ${body}\n\n`;
// Add comments
if (issue.comments && issue.comments > 0){
formattedText += ` Comments: ${issue.comments}\n\n`;
} else{
formattedText += ` Comments: 0\n\n`;
}
});
return formattedText;
}

export { displayDirectoryStructure, sortContents, getSelectedFiles, formatRepoContents, formatIssues };