Skip to content

[FEATURE] Apply branch filters #50

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

Merged
merged 4 commits into from
Aug 4, 2023
Merged
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
13 changes: 9 additions & 4 deletions html/branchSelection.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
d="M11.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122V6A2.5 2.5 0 0110 8.5H6a1 1 0 00-1 1v1.128a2.251 2.251 0 11-1.5 0V5.372a2.25 2.25 0 111.5 0v1.836A2.492 2.492 0 016 7h4a1 1 0 001-1v-.628A2.25 2.25 0 019.5 3.25zM4.25 12a.75.75 0 100 1.5.75.75 0 000-1.5zM3.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0z">
</path>
</svg>
<span class="css-truncate-target" data-menu-button="">All branches</span>
<span class="css-truncate-target" data-menu-button="" id = "branches-dropdown-button">All branches</span>
<span class="dropdown-caret"></span>
</summary>
<div class="SelectMenu">
Expand Down Expand Up @@ -73,16 +73,21 @@
<span hidden="{{ isNotDefault }}" class="Label Label--secondary flex-self-start">default</span>
</a>
</template>
<footer class="SelectMenu-footer"><a aria-disabled="true">Show selected branches</a>
<footer class="SelectMenu-footer">
<a class="Button--primary Button--medium Button btn-block mb-2"
data-toggle-for="branch-select-menu" id="branch-filter-button" style="justify-content: center;">
<span class="Button-label"><span class="d-none d-md-block">Show selected branches</span>
<span class="d-block d-md-none">Apply</span></span>
</a>
</footer>
</ref-selector>
</div>
</input-demux>
</div>
</div>
</details>
<img src="https://github.com/NirmalScaria/NirmalScaria.github.io/raw/master/assets/prompt.png" height="32px" class="ml-3" id="promptImage"
style="border-radius: 5px; display: none; cursor: pointer;">
<img src="https://github.com/NirmalScaria/NirmalScaria.github.io/raw/master/assets/prompt.png" height="32px"
class="ml-3" id="promptImage" style="border-radius: 5px; display: none; cursor: pointer;">
</div>
<div id="legendContainer" style="display: none;">
<summary class="btn css-truncate ml-2" value="" style=" pointer-events: none !important;" id="branchButton">
Expand Down
4 changes: 3 additions & 1 deletion js/fetchCommits.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,16 @@ async function fetchCommits() {
if (await fetchCommitsPage(repoOwner, repoName, "NONE")) {
console.log("--FETCHED BRANCHES--");
console.log("--COST : '" + APIcost + "'--");
var allBranchesObject = {}
branches = branches.map(branch => {
heads.push({
name: branch.name,
oid: branch.target.history.edges[0].node.oid,
});
allBranchesObject[branch.name] = branch.target.history.edges[0].node.oid;
branch.target.history.edges[0].node.isHead = true;
return branch;
})
await sortCommits(branches, heads);
await sortCommits(branches, heads, allBranchesObject);
}
}
185 changes: 185 additions & 0 deletions js/fetchFilteredCommits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@


async function fetchFilteredCommits(selectedBranchNames, selectedBranches, allBranches) {
var branches = [];
// Recurcively call this function unti all the branches are fetched
// (GitHub API has a limit of 100 branches per request)

var APIcost = 0;

// The cost depends on the complexity of query that GitHub will have to do
// First, fetch the commits with just the time, so that top ones to show can be found
// Then request the rest of the details (like parents) of commits in another request.
// NOTE : Return true if the request is successful, false otherwise
async function fetchCommitsPageFiltered(repoOwner, repoName, lastFetched) {
if (lastFetched == "NONE") {
console.log("--FETCHING COMMITS STARTED--");
}
else {
console.log("--STILL FETCHING... TOO MANY BRANCHES--");
}
var endpoint = "https://api.github.com/graphql";
if (lastFetched == "NONE") {
var initialQuery = `
fragment branch on Commit {
history(first: 10) {
edges {
node {
... on Commit {
oid
messageHeadlineHTML
committedDate
}
}
}
}
}

{
repository(owner: "` + repoOwner + `", name: "` + repoName + `") {
`;
for (var i = 0; i < selectedBranches.length; i++) {
initialQuery += encode(selectedBranchNames[i]) + ` : object(oid: "` + selectedBranches[i] + `") {
...branch
}
`;
}
initialQuery += `
}
rateLimit {
limit
cost
remaining
resetAt
}
}`;
}
else {
var initialQuery = `
{
repository(owner: "`+ repoOwner + '", name: "' + repoName + `") {
refs(refPrefix: "refs/heads/", orderBy: {direction: DESC, field: TAG_COMMIT_DATE}, first:100, after: "` + lastFetched + `") {
edges {
cursor
node {
... on Ref {
name
target {
... on Commit {
history(first: 10) {
edges {
node {
... on Commit {
oid
messageHeadlineHTML
committedDate
}
}
}
}
}
}
}
}
}
}
}
rateLimit {
limit
cost
remaining
resetAt
}
}`;
}
var headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + getLocalToken()
};
var body = {
query: initialQuery
};
var response = await fetch(endpoint, {
method: "POST",
headers: headers,
body: JSON.stringify(body)
});
if ((response.status != 200 && response.status != 201)) {
console.log("--ERROR FETCHING GRAPHQL--");
addAuthorizationPrompt("Failed to fetch commits. Make sure your GitHub account has access to the repository.");
return (false);
}
var data = await response.json();
if (data.error || data.errors) {
console.log("--ERROR FETCHING GRAPHQL--");
addAuthorizationPrompt("Failed to fetch commits. Make sure your GitHub account has access to the repository.");
return (false);
}
var fetchedBranches = [];
for (var branch in data.data.repository) {
var thisBranch = data.data.repository[branch];
thisBranch.name = decode(branch)
fetchedBranches.push(thisBranch);
}
fetchedBranches.forEach(branch => {
var commit = branch;
branches.push(commit);
});
if (fetchedBranches.length >= 100) {
var lastFetchedCursor = fetchedBranches[fetchedBranches.length - 1].cursor;
if (await fetchCommitsPageFiltered(repoOwner, repoName, lastFetchedCursor) == false) {
return (false);
};
}
APIcost += data.data.rateLimit.cost;
return (true);
}

var currentUrl = window.location.href;
var splitUrl = currentUrl.split('/');
var repoOwner = splitUrl[3]
var repoName = splitUrl[4];

var heads = [];

// fetchCommitsPage returns true only if the fetch was successful
if (await fetchCommitsPageFiltered(repoOwner, repoName, "NONE")) {
console.log("--FETCHED BRANCHES--");
console.log("--COST : '" + APIcost + "'--");
branches = branches.map(branch => {
heads.push({
name: branch.name,
oid: branch.history.edges[0].node.oid,
});
branch.target = {}
branch.target.history = branch.history;
branch.target.history.edges[0].node.isHead = true;
return branch;
})
await sortCommits(branches, heads, allBranches);
}
else {
console.log("Fetch failure");
}
}

// Branch names of git allows a lot of flexibiliity in variable naming
// Many special characters are allowed. But, graphql doesnt seem to accept all of it
// Hence, converting the UTF-8 characters to a 4 digit number for each character
// And decoding back.
function encode(string) {
var res = "XX"
for (var i = 0; i < string.length; i++) {
res += string.charCodeAt(i).toString().padStart(4, 0)
}
return (res)
}

function decode(string) {
string = string.substr(2)
var res = ""
for (var i = 0; i < string.length; i += 4) {
res += String.fromCharCode(parseInt(string.substr(i, 4)))
}
return (res)
}
4 changes: 2 additions & 2 deletions js/fetchFurther.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

// The idea is to fetch the last 20 commits in the history
// of each of the last 10 commits that are displayed.
async function fetchFurther(commits, allCommits, heads, pageNo, branchNames) {
async function fetchFurther(commits, allCommits, heads, pageNo, branchNames, allBranches) {
// commits array just contains the last 10 commits so that their
// 10 levels of history can be fetched.

Expand Down Expand Up @@ -119,6 +119,6 @@ async function fetchFurther(commits, allCommits, heads, pageNo, branchNames) {
});
pageNo += 1;
var commitsToShow = (allCommits.slice(0, 10 * pageNo));
await showCommits(commitsToShow, branchNames, allCommits, heads, pageNo);
await showCommits(commitsToShow, branchNames, allCommits, heads, pageNo, allBranches);
showLegend(heads);
}
40 changes: 36 additions & 4 deletions js/setBranchOptions.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
function setBranchOptions(branches, selectedBranchNames) {
function setBranchOptions(branches, selectedBranchNames, allBranches) {
var branchesContainer = document.getElementById("branches-list-parent");
var existingChild = branchesContainer.children[0];
var branchesDropdownButton = document.getElementById("branches-dropdown-button");

// Add each branch to the dropdown list.
Array.from(branches).forEach((branch) => {
var branchNames = new Set()
for (var branch in allBranches) {
var branchname = branch;
branchNames.add(branchname);
}
Array.from(branchNames).forEach((branch) => {
var newChild = existingChild.cloneNode(true);
newChild.children[1].innerHTML = branch;
newChild.setAttribute("branch-name", branch);
if(selectedBranchNames.includes(branch)){
newChild.setAttribute("aria-checked", "true");
}
else{
newChild.setAttribute("aria-checked", "false");
}
newChild.addEventListener("click", () => {
var thisItem = document.querySelector(`[branch-name="${branch}"]`);

Expand All @@ -29,6 +40,15 @@ function setBranchOptions(branches, selectedBranchNames) {
branchesContainer.appendChild(newChild);
});

if (branchNames.size == selectedBranchNames.length) {
branchesContainer.children[0].setAttribute("aria-checked", "true");
branchesDropdownButton.innerHTML = "All Branches";
}
else {
branchesContainer.children[0].setAttribute("aria-checked", "false");
branchesDropdownButton.innerHTML = "Select Branches";
}

// Action for the "All branches" button
branchesContainer.children[0].addEventListener("click", () => {
if (branchesContainer.children[0].getAttribute("aria-checked") == "true") {
Expand All @@ -51,5 +71,17 @@ function setBranchOptions(branches, selectedBranchNames) {
}
});
var sizedContainer = document.getElementById("branches-sized-container");
sizedContainer.style.height = (35 * branches.length + 45) + "px";
sizedContainer.style.height = (35 * branchNames.size + 25) + "px";

var branchFilterButton = document.getElementById("branch-filter-button");
var selectedBranchCommitIds = []

branchFilterButton.addEventListener("click", () => {
selectedBranchCommitIds = [];
for (var branch of selectedBranchNames) {
selectedBranchCommitIds.push(allBranches[branch]);
}
showCommitsLoading();
fetchFilteredCommits(selectedBranchNames, selectedBranchCommitIds, allBranches);
});
}
11 changes: 5 additions & 6 deletions js/showCommits.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ async function getCommitDetails(repoOwner, repoName, commits, allCommits) {
return ([commits, allCommits]);
}

async function showCommits(commits, branchNames, allCommits, heads, pageNo) {
async function showCommits(commits, branchNames, allCommits, heads, pageNo, allBranches) {
var presentUrl = window.location.href;
var repoOwner = presentUrl.split('/')[3];
var repoName = presentUrl.split('/')[4];
Expand Down Expand Up @@ -207,10 +207,10 @@ async function showCommits(commits, branchNames, allCommits, heads, pageNo) {

// Display the branches filter dropdown button with default value only (All branches)
await loadBranchesButton();
setBranchOptions(branchNames, branchNames);
setBranchOptions(branchNames, Object.keys(branchNames), allBranches);
contentView.appendChild(commitsOutsideContainer);

addNextPageButton(commits, branchNames, allCommits, heads, pageNo);
addNextPageButton(commits, branchNames, allCommits, heads, pageNo, allBranches);

drawGraph(commits, commitDict);

Expand Down Expand Up @@ -248,14 +248,13 @@ function relativeTime(date) {
return (output);
}

function addNextPageButton(commits, branchNames, allCommits, heads, pageNo) {
function addNextPageButton(commits, branchNames, allCommits, heads, pageNo, allBranches) {
var newerButton = document.getElementById("newerButton");
var olderButton = document.getElementById("olderButton");
if (commits.length >= 10) {
olderButton.setAttribute("aria-disabled", "false");
olderButton.addEventListener("click", function () {
// fetchFurther(commits, branchNames, allCommits, branches, heads, pageNo);
fetchFurther(commits.slice(-10), allCommits, heads, pageNo, branchNames);
fetchFurther(commits.slice(-10), allCommits, heads, pageNo, branchNames, allBranches);
});
}
}
Loading