-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Release v0.1: quick access to Files changed page and bulk comment (#1)
* update LICENSE Signed-off-by: Aolin <[email protected]> * README: add feature description, usage, and FAQs Signed-off-by: Aolin <[email protected]> * script: (CreateFileLink) add a File element to quick access to Files Changed page Signed-off-by: Aolin <[email protected]> * script: (GetRepositoryInformation) get the owner and name of the current GitHub repository Signed-off-by: Aolin <[email protected]> * script: (EnsureToken) prompt uses to add GitHub token Signed-off-by: Aolin <[email protected]> * script: (LeaveCommentOnPR) comment on PR using the GitHub issue API Signed-off-by: Aolin <[email protected]> * script: (CreateCommentButton) create a button to comment on multiple PRs Signed-off-by: Aolin <[email protected]> * script: add newline at the end Signed-off-by: Aolin <[email protected]> --------- Signed-off-by: Aolin <[email protected]>
- Loading branch information
Showing
3 changed files
with
174 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,32 @@ | ||
# octopus-github | ||
A GitHub extension | ||
|
||
A userscript for GitHub with the following features: | ||
|
||
- Quick access to the **Files changed** page of a PR | ||
- Bulk comment on multiple PRs | ||
|
||
## Usage | ||
|
||
1. Install a userscript manager of your choice, such as [Tampermonkey](https://tampermonkey.net/). | ||
|
||
2. Add the userscript by clicking [`gh-util.user.js`](https://raw.githubusercontent.com/Oreoxmt/octopus-github/main/gh-util.user.js). | ||
|
||
3. (Optional) Configure your own GitHub [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) (`repo` scope) when you use the bulk comment feature for the first time. | ||
|
||
## FAQs | ||
|
||
### Why is the bulk comment feature not working? | ||
|
||
1. Check if you have configured a Github personal access token. | ||
|
||
2. Check if the token has the `repo` scope. | ||
|
||
3. Check if the token has expired. | ||
|
||
### How to manage the token used by this script? | ||
|
||
1. Go to the **Developer Tools** of your browser and then click the **Application** tab. | ||
|
||
2. In the **Storage** section on the left panel, click **Local Storage > https://github.com**. | ||
|
||
3. Search for the key `octopus-github-util:token` and modify/delete it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// ==UserScript== | ||
// @name Octopus GitHub | ||
// @version 0.1 | ||
// @description A userscript for GitHub | ||
// @author Oreo | ||
// @match https://github.com/*/pulls* | ||
// @grant none | ||
// ==/UserScript== | ||
|
||
(function () { | ||
|
||
'use strict'; | ||
|
||
const STORAGEKEY = 'octopus-github-util:token' | ||
|
||
function GetRepositoryInformation() { | ||
// Get the pathname of the current page | ||
var pathname = location.pathname; | ||
|
||
// Split the pathname into an array of parts | ||
var parts = pathname.split('/'); | ||
|
||
// Return an object containing the user name and repository name | ||
return { | ||
owner: parts[1], | ||
name: parts[2], | ||
} | ||
} | ||
|
||
function EnsureToken() { | ||
var token = localStorage.getItem(STORAGEKEY) | ||
if (!token) { | ||
// Prompt user to set token | ||
// TODO: Use HTML element instead of prompt | ||
token = prompt('Enter your GitHub token:'); | ||
if (!token) { | ||
throw 'No token set' | ||
} | ||
localStorage.setItem(STORAGEKEY, token); | ||
} | ||
return token; | ||
} | ||
|
||
// This function can be used to leave a comment on a specific PR | ||
function LeaveCommentOnPR(commentLink, comment) { | ||
// Send the POST request to the GitHub API | ||
// TODO: Use Octokit to create requests | ||
fetch(commentLink, { | ||
method: 'POST', | ||
headers: { | ||
'Authorization': `Bearer ${EnsureToken()}`, | ||
'Accept': 'application/vnd.github+json', | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ | ||
'body': comment | ||
}) | ||
}).then((response) => { | ||
console.log('response to ', commentLink, response) | ||
}).catch((error) => { | ||
console.log('error on ', commentLink, error) | ||
}) | ||
} | ||
|
||
// TODO: Use toggle instead of button, and add more features to the toggle, e.g., editing tokens. | ||
function CreateCommentButton() { | ||
// First, find the "table-list-header-toggle" div | ||
var toggleDiv = document.querySelector('.table-list-header-toggle.float-right'); | ||
|
||
// Next, create a button element and add it to the page | ||
var button = document.createElement('button'); | ||
button.innerHTML = 'Comment'; | ||
button.setAttribute('class', 'btn btn-sm js-details-target d-inline-block float-left float-none m-0 mr-md-0 js-title-edit-button') | ||
toggleDiv.appendChild(button); | ||
|
||
// Next, add an event listener to the button to listen for clicks | ||
button.addEventListener('click', function () { | ||
EnsureToken(); | ||
|
||
// Get a list of all the checkboxes on the page (these are used to select PRs) | ||
var checkboxes = document.querySelectorAll('input[type=checkbox][data-check-all-item]'); | ||
|
||
// Iterate through the checkboxes and get the ones that are checked | ||
var selectedPRs = []; | ||
|
||
checkboxes.forEach(function (checkbox) { | ||
if (checkbox.checked) { | ||
selectedPRs.push(checkbox.value); | ||
} | ||
}) | ||
|
||
// Prompt the user for a comment to leave on the selected PRs | ||
var comment = prompt('Enter a comment to leave on the selected PRs:'); | ||
if (!comment) { | ||
return; | ||
} | ||
var repo = GetRepositoryInformation(); | ||
|
||
// Leave the comment on each selected PR | ||
selectedPRs.forEach(function (pr) { | ||
var commentLink = `https://api.github.com/repos/${repo.owner}/${repo.name}/issues/${pr}/comments`; | ||
// Leave a comment on the PR | ||
LeaveCommentOnPR(commentLink, comment); | ||
}); | ||
}); | ||
} | ||
|
||
function CreateFileLink() { | ||
|
||
// Get all div elements with an id that starts with "issue_" | ||
var issueElements = document.querySelectorAll('div[id^="issue_"]'); | ||
issueElements.forEach((element) => { | ||
var issueId = element.getAttribute("id") | ||
var originalLinkElement = document.getElementById(issueId + "_link") | ||
var originalLink = originalLinkElement.getAttribute("href") | ||
var newLink = originalLink + "/files" | ||
// Get all span elements within the current element | ||
var spanElements = element.querySelectorAll('span[class="opened-by"]'); | ||
if (spanElements.length == 1) { | ||
var openedBy = spanElements[0]; | ||
var linkSpanElement = document.createElement('span'); | ||
linkSpanElement.setAttribute('class', 'd-inline-block mr-1') | ||
var dotSpanElement = document.createElement('span'); | ||
dotSpanElement.innerHTML = ' • '; | ||
dotSpanElement.setAttribute('class', 'd-inline-block mr-1') | ||
var linkElement = document.createElement('a') | ||
linkElement.setAttribute('href', newLink) | ||
linkElement.setAttribute('class', 'Link--muted') | ||
linkElement.innerHTML = "Files" | ||
linkSpanElement.appendChild(linkElement) | ||
openedBy.insertAdjacentElement('beforebegin', linkSpanElement) | ||
openedBy.insertAdjacentElement('beforebegin', dotSpanElement); | ||
} | ||
}) | ||
|
||
} | ||
|
||
// TODO: Do this everytime on switching to new page | ||
CreateCommentButton(); | ||
CreateFileLink(); | ||
|
||
})(); |