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

show number of issues #10

Merged
merged 4 commits into from
Mar 19, 2016
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
22 changes: 11 additions & 11 deletions src/auth.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* global chrome, queryString, getSyncStorage, setSyncStorage */

const client_id = "1a3ac4d44a9e65a75a77";
const client_secret = "ab3c3a116e35d9fe11d409cb8c1205e9ae5a7e91";
const githubBaseUrl = "https://github.com/login/oauth/authorize";
const githubTokenUrl = "https://github.com/login/oauth/access_token";
const redirectUri = chrome.identity.getRedirectURL('provider_cb');

console.log(redirectUri);
const redirectUri = chrome.identity.getRedirectURL("provider_cb");

const getAuthUrl = (base, callbackUrl, scope) => {
let obj = {
Expand All @@ -15,7 +15,7 @@ const getAuthUrl = (base, callbackUrl, scope) => {
};

return `${base}?${queryString.stringify(obj)}`;
}
};

function getTokenFromCode(code) {
let obj = {
Expand All @@ -25,7 +25,7 @@ function getTokenFromCode(code) {
};

return fetch(`${githubTokenUrl}?${queryString.stringify(obj)}`)
.then((res) => res.text(), (err) => {
.then((res) => res.text(), () => {
throw new Error("Failed to get access_token");
});
}
Expand Down Expand Up @@ -62,29 +62,29 @@ function getToken(url, interactive) {
resolve(access_token);
});
} else {
reject(new Error ('neither access_token nor code available'));
reject(new Error ("neither access_token nor code available"));
}
} else {
reject(new Error('Invalid redirect URI'));
reject(new Error("Invalid redirect URI"));
}
});
});
}

function getTokenFromOauth() {
getSyncStorage({ 'access_token': null })
getSyncStorage({ "access_token": null })
.then((res) => {
if (!res.access_token) {
const url = getAuthUrl(githubBaseUrl, redirectUri, 'public_repo');
const url = getAuthUrl(githubBaseUrl, redirectUri, "public_repo");
getToken(url, true)
.then((token) => {
setSyncStorage({ 'access_token': token });
setSyncStorage({ "access_token": token });
const accessTokenInput = document.getElementById("token-input");
accessTokenInput.value = token;
document.querySelector("#feedback").textContent = "Access Token Set!";
}, (message) => {
document.querySelector("#feedback").textContent = message;
})
});
} else {
document.querySelector("#feedback").textContent = "Access Token Already Set!";
}
Expand Down
3 changes: 2 additions & 1 deletion src/content.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
}

#gce-update:hover ~ #gce-update-time,
#gce-num-prs:hover ~ #gce-update-time {
#gce-num-prs:hover ~ #gce-update-time,
#gce-num-issues:hover ~ #gce-update-time {
display: block;
}
134 changes: 84 additions & 50 deletions src/content.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use strict";

/* global chrome, getSyncStorage, setStorage, getStorage */
/* global $, getSyncStorage, setStorage, getStorage, gitHubInjection */

const isPR = (path) => /^\/[^/]+\/[^/]+\/pull\/\d+/.test(path);
const isIssue = (path) => /^\/[^/]+\/[^/]+\/issues\/\d+/.test(path);
const getCurrentUser = () => $('.js-menu-target img').attr('alt').slice(1) || "";
const getCurrentUser = () => $(".js-menu-target img").attr("alt").slice(1) || "";
const isPrivate = () => $(".repo-private-label").length > 0;

function getContributor() {
let $contributor = $(".timeline-comment-wrapper .timeline-comment-header-text strong");
Expand All @@ -18,13 +19,13 @@ function getContributorInfo() {
let pathNameArr = location.pathname.split("/");
let org = pathNameArr[1]; // babel
let repo = pathNameArr[2]; // babel-eslint
let currentPR = pathNameArr[4]; // 3390
let currentNum = pathNameArr[4]; // 3390
let repoPath = org + "/" + repo; // babel/babel-eslint
let contributor = getContributor();

let ret = {
contributor: getContributor(),
currentPR,
contributor,
currentNum,
repoPath
};

Expand All @@ -46,7 +47,7 @@ function buildUrl({base, q: {type, filterUser, author, repo}, sort, order, per_p
return query;
}

function contributorCount({access_token, contributor, repoPath, type}) {
function contributorCount({access_token, contributor, repoPath, old = {}, type}) {
let searchURL = buildUrl({
access_token,
base: "https://api.github.com/search/issues",
Expand All @@ -68,34 +69,52 @@ function contributorCount({access_token, contributor, repoPath, type}) {
}

let obj = {
prs: json.total_count,
lastUpdate: Date.now()
};

if (json.items && json.items.length) {
obj.firstPRNumber = json.items[0].number;
if (type === "pr") {
obj.prs = json.total_count;
} else if (type === "issue") {
obj.issues = json.total_count;
}

if (obj.prs) {
setStorage(contributor, repoPath, obj);
if (json.items && json.items.length) {
obj[`first${type[0].toUpperCase() + type.slice(1)}Number`] = json.items[0].number;
}

obj = Object.assign(old, obj);

setStorage(contributor, repoPath, obj);

return obj;
});
}

function appendPRText(currentPR, repoInfo) {
let {prs, firstPRNumber} = repoInfo;
let text = `${prs} PRs`;
function appendPRText(currentNum, repoInfo) {
let {issues, prs, firstPrNumber, firstIssueNumber} = repoInfo;

if (prs !== undefined) {
let prText = `${prs} PRs`;
if (firstPrNumber === +currentNum) {
prText = "First PR";
if (prs > 1) {
prText += ` out of ${prs} (to the repo)`;
}
}
repoInfo.prText = prText;
}

if (firstPRNumber === +currentPR) {
text = "First PR";
if (prs > 1) {
text += ` out of ${prs} (to the repo)`;
if (issues !== undefined) {
let issueText = `${issues} Issues`;
if (firstIssueNumber === +currentNum) {
issueText = "First Issue";
if (issues > 1) {
issueText += ` out of ${issues} (to the repo)`;
}
}
repoInfo.issueText = issueText;
}

repoInfo.text = text;
return repoInfo;
}

Expand All @@ -108,69 +127,82 @@ function makeUpdateLabel(time) {
}

function injectInitialUI({ contributor, repoPath }) {
if ($("#gce-num-prs").length) return;

let $elem = $(".timeline-comment-header-text").first();
let id = "gce-num-prs";
let prText = makeLabel("Loading # of PRs..");
let updateText = makeLabel("🔄 PRs");

if (!$(id).length) {
$elem.before(`<a href="/${repoPath}/pulls?utf8=%E2%9C%93&q=is:both+is:pr+author:${contributor}" id="${id}">${prText}</a>`);
$elem.before(`<a style="cursor:pointer;" id="gce-update">${updateText}</a>`);
$elem.before(`<a id="gce-update-time" class="timeline-comment-label">N/A</a>`);

let $update = $("#gce-update");
$update.dom[0].addEventListener("click", function() {
setStorage(contributor, repoPath, {});
update(getContributorInfo());
});
}
let prId = "gce-num-prs";
let prText = makeLabel("Loading..");

if ($(`#${prId}`).length) return;

let issueId = "gce-num-issues";
let issueText = makeLabel("Loading..");
let updateText = makeLabel("🔄");

$elem.before(`<a href="/${repoPath}/pulls?utf8=%E2%9C%93&q=is:both+is:pr+author:${contributor}" id="${prId}">${prText}</a>`);
$elem.before(`<a href="/${repoPath}/issues?utf8=%E2%9C%93&q=is:both+is:issue+author:${contributor}" id="${issueId}">${issueText}</a>`);
$elem.before(`<a style="cursor:pointer;" id="gce-update">${updateText}</a>`);
$elem.before(`<a id="gce-update-time" class="timeline-comment-label">N/A</a>`);

let $update = $("#gce-update");
$update.dom[0].addEventListener("click", function() {
setStorage(contributor, repoPath, {});
update(getContributorInfo());
});
}

function updatePRText({ text, lastUpdate }) {
let prText = $("#gce-num-prs .timeline-comment-label");
if (prText.length) {
prText.text(text);
function updateTextNodes({ prText, issueText, lastUpdate }) {
let prNode = $("#gce-num-prs .timeline-comment-label");
if (prNode.length) {
prNode.text(prText);
}

let issueNode = $("#gce-num-issues .timeline-comment-label");
if (issueNode.length) {
issueNode.text(issueText);
}

let updateTime = $("#gce-update-time");
if (updateTime && typeof lastUpdate === "number") {
updateTime.html(`<span>Last Updated </span>${makeUpdateLabel(new Date(lastUpdate))}`);
}
}

function update({ contributor, repoPath, currentPR }) {
function update({ contributor, repoPath, currentNum }) {
getStorage(contributor, repoPath)
.then((storage) => {
let storageRes = storage[contributor][repoPath];
if (storageRes.prs) {
updatePRText(appendPRText(currentPR, storageRes));
if (storageRes.prs || storageRes.issues) {
updateTextNodes(appendPRText(currentNum, storageRes));
} else {
getSyncStorage({ "access_token": null })
.then((res) => {
contributorCount({ access_token: res.access_token, type: "pr", contributor, repoPath})
.then((repoInfo) => {
Promise.all([
contributorCount({ old: storageRes, access_token: res.access_token, type: "pr", contributor, repoPath}),
contributorCount({ old: storageRes, access_token: res.access_token, type: "issue", contributor, repoPath})
])
.then(([prInfo, issueInfo]) => {
let repoInfo = Object.assign(prInfo, issueInfo);

if (repoInfo.errors) {
updatePRText(repoInfo.errors[0].message);
updateTextNodes(repoInfo.errors[0].message);
return;
}

if (repoInfo.message) {
// API rate limit exceeded for hzoo.
if (repoInfo.message.indexOf(`API rate limit exceeded for ${getCurrentUser()}`) >= 0) {
updatePRText("More than 30 req/min :D");
updateTextNodes("More than 30 req/min :D");
return;
}

// API rate limit exceeded for x.x.x.x.
// (But here's the good news: Authenticated requests get a higher rate limit.
// Check out the documentation for more details.)
if (repoInfo.message.indexOf("the good news") >= 0) {
updatePRText("More than 10 req/min: Maybe add a access_token!");
updateTextNodes("More than 10 req/min: Maybe add a access_token!");
return;
}
}
updatePRText(appendPRText(currentPR, repoInfo));
updateTextNodes(appendPRText(currentNum, repoInfo));
});
});
}
Expand All @@ -179,10 +211,12 @@ function update({ contributor, repoPath, currentPR }) {

document.addEventListener("DOMContentLoaded", () => {
gitHubInjection(window, () => {
// if (isPrivate()) return;

if (isPR(location.pathname) || isIssue(location.pathname)) {
if (getContributor()) {
update(getContributorInfo());
}
};
}
});
});
5 changes: 5 additions & 0 deletions src/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
background-color: #f0ad4e;
text-align: center;
}
#clear-cache {
text-align: center;
cursor: pointer;
}
</style>
<script src="vendor/query-string.js"></script>
<script src="auth.js"></script>
Expand All @@ -33,6 +37,7 @@ <h1 class="description">
<h1>Access Token</h1>
<input type="text" id="token-input" placeholder="Paste your access token here">
<p id="feedback"></p>
<h3 id="clear-cache"><a>Clear Contributor Data</a></h3>
</section>
<h5>Github's Search API Rate Limit</h5>
<section>
Expand Down
15 changes: 13 additions & 2 deletions src/options.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* global getSyncStorage, setSyncStorage */
/* global getSyncStorage, setSyncStorage, clearSyncStorage, getTokenFromOauth */

document.addEventListener("DOMContentLoaded", () => {
const accessTokenInput = document.getElementById("token-input");
const oauthLink = document.getElementById("use-oauth");
const clearCacheLink = document.getElementById("clear-cache");

getSyncStorage({ "access_token": null })
.then(({ access_token }) => {
Expand All @@ -15,5 +16,15 @@ document.addEventListener("DOMContentLoaded", () => {

oauthLink.addEventListener("click", () => {
getTokenFromOauth();
})
});

clearCacheLink.addEventListener("click", () => {
let temp = accessTokenInput.value;
clearSyncStorage()
.then(() => {
setSyncStorage({ "access_token": temp });
document.querySelector("#feedback").textContent = "Storage Cleared";
});
});
});

1 change: 1 addition & 0 deletions src/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function promisify(func) {

window.getSyncStorage = promisify(chrome.storage.sync.get.bind(chrome.storage.sync));
window.setSyncStorage = promisify(chrome.storage.sync.set.bind(chrome.storage.sync));
window.clearSyncStorage = promisify(chrome.storage.sync.clear.bind(chrome.storage.sync));

window.setStorage = (CONTRIBUTOR, ORG_REPO_PATH, value) => {
return window.setSyncStorage({
Expand Down