Skip to content

Commit 3bba385

Browse files
authored
[FEATURE] Apply branch filters
2 parents 3fb7e15 + 5b2116e commit 3bba385

File tree

8 files changed

+264
-23
lines changed

8 files changed

+264
-23
lines changed

html/branchSelection.html

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
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">
1212
</path>
1313
</svg>
14-
<span class="css-truncate-target" data-menu-button="">All branches</span>
14+
<span class="css-truncate-target" data-menu-button="" id = "branches-dropdown-button">All branches</span>
1515
<span class="dropdown-caret"></span>
1616
</summary>
1717
<div class="SelectMenu">
@@ -73,16 +73,21 @@
7373
<span hidden="{{ isNotDefault }}" class="Label Label--secondary flex-self-start">default</span>
7474
</a>
7575
</template>
76-
<footer class="SelectMenu-footer"><a aria-disabled="true">Show selected branches</a>
76+
<footer class="SelectMenu-footer">
77+
<a class="Button--primary Button--medium Button btn-block mb-2"
78+
data-toggle-for="branch-select-menu" id="branch-filter-button" style="justify-content: center;">
79+
<span class="Button-label"><span class="d-none d-md-block">Show selected branches</span>
80+
<span class="d-block d-md-none">Apply</span></span>
81+
</a>
7782
</footer>
7883
</ref-selector>
7984
</div>
8085
</input-demux>
8186
</div>
8287
</div>
8388
</details>
84-
<img src="https://github.com/NirmalScaria/NirmalScaria.github.io/raw/master/assets/prompt.png" height="32px" class="ml-3" id="promptImage"
85-
style="border-radius: 5px; display: none; cursor: pointer;">
89+
<img src="https://github.com/NirmalScaria/NirmalScaria.github.io/raw/master/assets/prompt.png" height="32px"
90+
class="ml-3" id="promptImage" style="border-radius: 5px; display: none; cursor: pointer;">
8691
</div>
8792
<div id="legendContainer" style="display: none;">
8893
<summary class="btn css-truncate ml-2" value="" style=" pointer-events: none !important;" id="branchButton">

js/fetchCommits.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,16 @@ async function fetchCommits() {
142142
if (await fetchCommitsPage(repoOwner, repoName, "NONE")) {
143143
console.log("--FETCHED BRANCHES--");
144144
console.log("--COST : '" + APIcost + "'--");
145+
var allBranchesObject = {}
145146
branches = branches.map(branch => {
146147
heads.push({
147148
name: branch.name,
148149
oid: branch.target.history.edges[0].node.oid,
149150
});
151+
allBranchesObject[branch.name] = branch.target.history.edges[0].node.oid;
150152
branch.target.history.edges[0].node.isHead = true;
151153
return branch;
152154
})
153-
await sortCommits(branches, heads);
155+
await sortCommits(branches, heads, allBranchesObject);
154156
}
155157
}

js/fetchFilteredCommits.js

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
2+
3+
async function fetchFilteredCommits(selectedBranchNames, selectedBranches, allBranches) {
4+
var branches = [];
5+
// Recurcively call this function unti all the branches are fetched
6+
// (GitHub API has a limit of 100 branches per request)
7+
8+
var APIcost = 0;
9+
10+
// The cost depends on the complexity of query that GitHub will have to do
11+
// First, fetch the commits with just the time, so that top ones to show can be found
12+
// Then request the rest of the details (like parents) of commits in another request.
13+
// NOTE : Return true if the request is successful, false otherwise
14+
async function fetchCommitsPageFiltered(repoOwner, repoName, lastFetched) {
15+
if (lastFetched == "NONE") {
16+
console.log("--FETCHING COMMITS STARTED--");
17+
}
18+
else {
19+
console.log("--STILL FETCHING... TOO MANY BRANCHES--");
20+
}
21+
var endpoint = "https://api.github.com/graphql";
22+
if (lastFetched == "NONE") {
23+
var initialQuery = `
24+
fragment branch on Commit {
25+
history(first: 10) {
26+
edges {
27+
node {
28+
... on Commit {
29+
oid
30+
messageHeadlineHTML
31+
committedDate
32+
}
33+
}
34+
}
35+
}
36+
}
37+
38+
{
39+
repository(owner: "` + repoOwner + `", name: "` + repoName + `") {
40+
`;
41+
for (var i = 0; i < selectedBranches.length; i++) {
42+
initialQuery += encode(selectedBranchNames[i]) + ` : object(oid: "` + selectedBranches[i] + `") {
43+
...branch
44+
}
45+
`;
46+
}
47+
initialQuery += `
48+
}
49+
rateLimit {
50+
limit
51+
cost
52+
remaining
53+
resetAt
54+
}
55+
}`;
56+
}
57+
else {
58+
var initialQuery = `
59+
{
60+
repository(owner: "`+ repoOwner + '", name: "' + repoName + `") {
61+
refs(refPrefix: "refs/heads/", orderBy: {direction: DESC, field: TAG_COMMIT_DATE}, first:100, after: "` + lastFetched + `") {
62+
edges {
63+
cursor
64+
node {
65+
... on Ref {
66+
name
67+
target {
68+
... on Commit {
69+
history(first: 10) {
70+
edges {
71+
node {
72+
... on Commit {
73+
oid
74+
messageHeadlineHTML
75+
committedDate
76+
}
77+
}
78+
}
79+
}
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}
87+
rateLimit {
88+
limit
89+
cost
90+
remaining
91+
resetAt
92+
}
93+
}`;
94+
}
95+
var headers = {
96+
"Content-Type": "application/json",
97+
"Authorization": "Bearer " + getLocalToken()
98+
};
99+
var body = {
100+
query: initialQuery
101+
};
102+
var response = await fetch(endpoint, {
103+
method: "POST",
104+
headers: headers,
105+
body: JSON.stringify(body)
106+
});
107+
if ((response.status != 200 && response.status != 201)) {
108+
console.log("--ERROR FETCHING GRAPHQL--");
109+
addAuthorizationPrompt("Failed to fetch commits. Make sure your GitHub account has access to the repository.");
110+
return (false);
111+
}
112+
var data = await response.json();
113+
if (data.error || data.errors) {
114+
console.log("--ERROR FETCHING GRAPHQL--");
115+
addAuthorizationPrompt("Failed to fetch commits. Make sure your GitHub account has access to the repository.");
116+
return (false);
117+
}
118+
var fetchedBranches = [];
119+
for (var branch in data.data.repository) {
120+
var thisBranch = data.data.repository[branch];
121+
thisBranch.name = decode(branch)
122+
fetchedBranches.push(thisBranch);
123+
}
124+
fetchedBranches.forEach(branch => {
125+
var commit = branch;
126+
branches.push(commit);
127+
});
128+
if (fetchedBranches.length >= 100) {
129+
var lastFetchedCursor = fetchedBranches[fetchedBranches.length - 1].cursor;
130+
if (await fetchCommitsPageFiltered(repoOwner, repoName, lastFetchedCursor) == false) {
131+
return (false);
132+
};
133+
}
134+
APIcost += data.data.rateLimit.cost;
135+
return (true);
136+
}
137+
138+
var currentUrl = window.location.href;
139+
var splitUrl = currentUrl.split('/');
140+
var repoOwner = splitUrl[3]
141+
var repoName = splitUrl[4];
142+
143+
var heads = [];
144+
145+
// fetchCommitsPage returns true only if the fetch was successful
146+
if (await fetchCommitsPageFiltered(repoOwner, repoName, "NONE")) {
147+
console.log("--FETCHED BRANCHES--");
148+
console.log("--COST : '" + APIcost + "'--");
149+
branches = branches.map(branch => {
150+
heads.push({
151+
name: branch.name,
152+
oid: branch.history.edges[0].node.oid,
153+
});
154+
branch.target = {}
155+
branch.target.history = branch.history;
156+
branch.target.history.edges[0].node.isHead = true;
157+
return branch;
158+
})
159+
await sortCommits(branches, heads, allBranches);
160+
}
161+
else {
162+
console.log("Fetch failure");
163+
}
164+
}
165+
166+
// Branch names of git allows a lot of flexibiliity in variable naming
167+
// Many special characters are allowed. But, graphql doesnt seem to accept all of it
168+
// Hence, converting the UTF-8 characters to a 4 digit number for each character
169+
// And decoding back.
170+
function encode(string) {
171+
var res = "XX"
172+
for (var i = 0; i < string.length; i++) {
173+
res += string.charCodeAt(i).toString().padStart(4, 0)
174+
}
175+
return (res)
176+
}
177+
178+
function decode(string) {
179+
string = string.substr(2)
180+
var res = ""
181+
for (var i = 0; i < string.length; i += 4) {
182+
res += String.fromCharCode(parseInt(string.substr(i, 4)))
183+
}
184+
return (res)
185+
}

js/fetchFurther.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

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

@@ -119,6 +119,6 @@ async function fetchFurther(commits, allCommits, heads, pageNo, branchNames) {
119119
});
120120
pageNo += 1;
121121
var commitsToShow = (allCommits.slice(0, 10 * pageNo));
122-
await showCommits(commitsToShow, branchNames, allCommits, heads, pageNo);
122+
await showCommits(commitsToShow, branchNames, allCommits, heads, pageNo, allBranches);
123123
showLegend(heads);
124124
}

js/setBranchOptions.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
function setBranchOptions(branches, selectedBranchNames) {
1+
function setBranchOptions(branches, selectedBranchNames, allBranches) {
22
var branchesContainer = document.getElementById("branches-list-parent");
33
var existingChild = branchesContainer.children[0];
4+
var branchesDropdownButton = document.getElementById("branches-dropdown-button");
45

5-
// Add each branch to the dropdown list.
6-
Array.from(branches).forEach((branch) => {
6+
var branchNames = new Set()
7+
for (var branch in allBranches) {
8+
var branchname = branch;
9+
branchNames.add(branchname);
10+
}
11+
Array.from(branchNames).forEach((branch) => {
712
var newChild = existingChild.cloneNode(true);
813
newChild.children[1].innerHTML = branch;
914
newChild.setAttribute("branch-name", branch);
15+
if(selectedBranchNames.includes(branch)){
16+
newChild.setAttribute("aria-checked", "true");
17+
}
18+
else{
19+
newChild.setAttribute("aria-checked", "false");
20+
}
1021
newChild.addEventListener("click", () => {
1122
var thisItem = document.querySelector(`[branch-name="${branch}"]`);
1223

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

43+
if (branchNames.size == selectedBranchNames.length) {
44+
branchesContainer.children[0].setAttribute("aria-checked", "true");
45+
branchesDropdownButton.innerHTML = "All Branches";
46+
}
47+
else {
48+
branchesContainer.children[0].setAttribute("aria-checked", "false");
49+
branchesDropdownButton.innerHTML = "Select Branches";
50+
}
51+
3252
// Action for the "All branches" button
3353
branchesContainer.children[0].addEventListener("click", () => {
3454
if (branchesContainer.children[0].getAttribute("aria-checked") == "true") {
@@ -51,5 +71,17 @@ function setBranchOptions(branches, selectedBranchNames) {
5171
}
5272
});
5373
var sizedContainer = document.getElementById("branches-sized-container");
54-
sizedContainer.style.height = (35 * branches.length + 45) + "px";
74+
sizedContainer.style.height = (35 * branchNames.size + 25) + "px";
75+
76+
var branchFilterButton = document.getElementById("branch-filter-button");
77+
var selectedBranchCommitIds = []
78+
79+
branchFilterButton.addEventListener("click", () => {
80+
selectedBranchCommitIds = [];
81+
for (var branch of selectedBranchNames) {
82+
selectedBranchCommitIds.push(allBranches[branch]);
83+
}
84+
showCommitsLoading();
85+
fetchFilteredCommits(selectedBranchNames, selectedBranchCommitIds, allBranches);
86+
});
5587
}

js/showCommits.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ async function getCommitDetails(repoOwner, repoName, commits, allCommits) {
144144
return ([commits, allCommits]);
145145
}
146146

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

208208
// Display the branches filter dropdown button with default value only (All branches)
209209
await loadBranchesButton();
210-
setBranchOptions(branchNames, branchNames);
210+
setBranchOptions(branchNames, Object.keys(branchNames), allBranches);
211211
contentView.appendChild(commitsOutsideContainer);
212212

213-
addNextPageButton(commits, branchNames, allCommits, heads, pageNo);
213+
addNextPageButton(commits, branchNames, allCommits, heads, pageNo, allBranches);
214214

215215
drawGraph(commits, commitDict);
216216

@@ -248,14 +248,13 @@ function relativeTime(date) {
248248
return (output);
249249
}
250250

251-
function addNextPageButton(commits, branchNames, allCommits, heads, pageNo) {
251+
function addNextPageButton(commits, branchNames, allCommits, heads, pageNo, allBranches) {
252252
var newerButton = document.getElementById("newerButton");
253253
var olderButton = document.getElementById("olderButton");
254254
if (commits.length >= 10) {
255255
olderButton.setAttribute("aria-disabled", "false");
256256
olderButton.addEventListener("click", function () {
257-
// fetchFurther(commits, branchNames, allCommits, branches, heads, pageNo);
258-
fetchFurther(commits.slice(-10), allCommits, heads, pageNo, branchNames);
257+
fetchFurther(commits.slice(-10), allCommits, heads, pageNo, branchNames, allBranches);
259258
});
260259
}
261260
}

0 commit comments

Comments
 (0)