From 7ee6642386a8087577635303b5b9bf3702b24cac Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Fri, 1 Dec 2017 08:34:44 +0100 Subject: [PATCH 1/7] matches has to be extended pretty wildly --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index 975fb25..663f420 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "wakatime-review", "version": "1.0", - "description": "Measure time spent on review and sends it to wakatime", + "description": "Measures time spent on review and sends it to wakatime", "icons": { "48": "icons/pull_request-48.png" @@ -20,7 +20,7 @@ "content_scripts": [ { - "matches": ["*://bitbucket.org/*/pull-requests/*"], + "matches": ["*://*/pull-requests/*"], "js": ["wakatime-review.js"] } ], From 36eda6241b527f690b0aaf56eb0e2a6cfb6382a5 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Fri, 1 Dec 2017 08:34:58 +0100 Subject: [PATCH 2/7] Prototype function factory --- wakatime-review.js | 77 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/wakatime-review.js b/wakatime-review.js index cc12c44..153ad99 100644 --- a/wakatime-review.js +++ b/wakatime-review.js @@ -1,7 +1,54 @@ +const bitbucket = { + readBranch: () => document.querySelector("#id_source_group .branch a").textContent, + readDomainOwnerAndProject: (url) => { + const regexp = /http[s]?:\/\/([a-zA-Z0-9]*\.[a-z]*)\/(\w*)\/([\w-]*).*/g; + const matched = regexp.exec(url); + const domain = matched[1]; + const owner = matched[2]; + const project = matched[3]; + return {owner: owner, + project: project}; + } +}; + +const stash = { + readBranch: () => { + console.log('stash readBranch'); + }, + readDomainOwnerAndProject: (url) => { + console.log('stash readDomainOwnerAndProject'); + return { + owner: 'stash', + project: 'project' + }; + } +}; + +const funcFactory = (url) => { + let siteParser; + + const parsedUrl = new URL(url); + if (parsedUrl.host.includes('stash')) { + siteParser = stash; + } else if (parsedUrl.host.includes('bitbucket')) { + siteParser = bitbucket; + } + + return siteParser.readDomainOwnerAndProject, siteParser.readBranch; +}; + function trackTime(keyPromise) { - const {domain, owner, project} = readDomainOwnerAndProject(); + // TODO: read branch + // TODO: readDomainOwnerAndProject + // TODO: preparePayload accept editor + + const url = window.location.href; + console.log(url); + const {readDomainOwnerAndProject, readBranch} = funcFactory(url); + + const {domain, owner, project} = readDomainOwnerAndProject(url); const branch = readBranch(); - const entity = "bitbucket.org"; + const entity = "bitbucket.org"; // TODO let havenOnlyScrolledInCurrentInterval = false; function scrollHandler() { @@ -15,20 +62,20 @@ function trackTime(keyPromise) { } }, 30000); - function readDomainOwnerAndProject() { - const url = window.location.href; - const regexp = /http[s]?:\/\/([a-zA-Z0-9]*\.[a-z]*)\/(\w*)\/([\w-]*).*/g; - const matched = regexp.exec(url); - const domain = matched[1]; - const owner = matched[2]; - const project = matched[3]; - return {owner: owner, - project: project}; - } + // function readDomainOwnerAndProject() { + // const url = window.location.href; + // const regexp = /http[s]?:\/\/([a-zA-Z0-9]*\.[a-z]*)\/(\w*)\/([\w-]*).*/g; + // const matched = regexp.exec(url); + // const domain = matched[1]; + // const owner = matched[2]; + // const project = matched[3]; + // return {owner: owner, + // project: project}; + // } - function readBranch() { - return document.querySelector("#id_source_group .branch a").textContent; - } + // function readBranch() { + // return document.querySelector("#id_source_group .branch a").textContent; + // } function preparePayload(entity, type, project, branch, is_write) { return { From 359c8dc581d2b27f58588dbd06cf68e7db2a3384 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Sat, 2 Dec 2017 16:37:42 +0100 Subject: [PATCH 3/7] Add stash support --- manifest.json | 2 +- options.html | 2 +- wakatime-review.js | 73 +++++++++++++++++++++------------------------- 3 files changed, 35 insertions(+), 42 deletions(-) diff --git a/manifest.json b/manifest.json index 663f420..33f9b1d 100644 --- a/manifest.json +++ b/manifest.json @@ -20,7 +20,7 @@ "content_scripts": [ { - "matches": ["*://*/pull-requests/*"], + "matches": [""], "js": ["wakatime-review.js"] } ], diff --git a/options.html b/options.html index d83a2a6..fbe8cb7 100644 --- a/options.html +++ b/options.html @@ -8,7 +8,7 @@
- +
diff --git a/wakatime-review.js b/wakatime-review.js index 153ad99..2a73660 100644 --- a/wakatime-review.js +++ b/wakatime-review.js @@ -1,54 +1,62 @@ + const bitbucket = { readBranch: () => document.querySelector("#id_source_group .branch a").textContent, - readDomainOwnerAndProject: (url) => { + readDomainOwnerAndProject: () => { + const url = window.location.href; const regexp = /http[s]?:\/\/([a-zA-Z0-9]*\.[a-z]*)\/(\w*)\/([\w-]*).*/g; const matched = regexp.exec(url); const domain = matched[1]; const owner = matched[2]; const project = matched[3]; - return {owner: owner, - project: project}; + return { + domain: domain, + owner: owner, + project: project + }; } }; + const stash = { - readBranch: () => { - console.log('stash readBranch'); - }, - readDomainOwnerAndProject: (url) => { - console.log('stash readDomainOwnerAndProject'); + readBranch: () => document.querySelector('div.pull-request-branches').textContent, + readDomainOwnerAndProject: () => { + + let grabAfter = (array, after) => { + return array[array.lastIndexOf(after) + 1]; + }; + + const url = new URL(window.location.href); + // example of URL to parse + // https://stash.clearcode.cc/projects/CCADS/repos/backend/pull-requests/137/commits + const splitUrl = url.pathname.split('/'); return { - owner: 'stash', - project: 'project' + domain: url.host, + owner: grabAfter(splitUrl, 'projects'), + project: grabAfter(splitUrl, 'repos') }; } }; -const funcFactory = (url) => { +const funcFactory = () => { let siteParser; + const parsedUrl = new URL(window.location.href); - const parsedUrl = new URL(url); if (parsedUrl.host.includes('stash')) { siteParser = stash; } else if (parsedUrl.host.includes('bitbucket')) { siteParser = bitbucket; } - return siteParser.readDomainOwnerAndProject, siteParser.readBranch; + return { + readDomainOwnerAndProject: siteParser.readDomainOwnerAndProject, + readBranch: siteParser.readBranch + }; }; function trackTime(keyPromise) { - // TODO: read branch - // TODO: readDomainOwnerAndProject - // TODO: preparePayload accept editor - - const url = window.location.href; - console.log(url); - const {readDomainOwnerAndProject, readBranch} = funcFactory(url); - - const {domain, owner, project} = readDomainOwnerAndProject(url); + const {readDomainOwnerAndProject, readBranch} = funcFactory(); + const {entity, owner, project} = readDomainOwnerAndProject(); const branch = readBranch(); - const entity = "bitbucket.org"; // TODO let havenOnlyScrolledInCurrentInterval = false; function scrollHandler() { @@ -62,30 +70,15 @@ function trackTime(keyPromise) { } }, 30000); - // function readDomainOwnerAndProject() { - // const url = window.location.href; - // const regexp = /http[s]?:\/\/([a-zA-Z0-9]*\.[a-z]*)\/(\w*)\/([\w-]*).*/g; - // const matched = regexp.exec(url); - // const domain = matched[1]; - // const owner = matched[2]; - // const project = matched[3]; - // return {owner: owner, - // project: project}; - // } - - // function readBranch() { - // return document.querySelector("#id_source_group .branch a").textContent; - // } - function preparePayload(entity, type, project, branch, is_write) { return { entity: entity, type: type, - time: (new Date).getTime()/1000, + time: new Date().getTime()/1000, project: project, branch: branch, is_write: is_write, - editor: "bitbucket.org" + editor: entity }; } From 3fb5d1523a45b5e61f21eefb127ef86c4e431060 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Tue, 5 Dec 2017 20:12:27 +0100 Subject: [PATCH 4/7] Add jshintrc with esversion --- .jshintrc | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .jshintrc diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..53b202c --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "esversion": 6 +} \ No newline at end of file From d5e0220173fac666cf39e8dc59bc83a8e89c7842 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Tue, 5 Dec 2017 20:12:45 +0100 Subject: [PATCH 5/7] Run code only on supported sites. --- wakatime-review.js | 115 +++++++++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/wakatime-review.js b/wakatime-review.js index 2a73660..02269b0 100644 --- a/wakatime-review.js +++ b/wakatime-review.js @@ -1,4 +1,3 @@ - const bitbucket = { readBranch: () => document.querySelector("#id_source_group .branch a").textContent, readDomainOwnerAndProject: () => { @@ -13,7 +12,9 @@ const bitbucket = { owner: owner, project: project }; - } + }, + // site support function + siteMatch: (url) => {} }; @@ -34,9 +35,14 @@ const stash = { owner: grabAfter(splitUrl, 'projects'), project: grabAfter(splitUrl, 'repos') }; - } + }, + siteMatch: (url) => {} }; + +const supportedSites = [bitbucket, stash]; + + const funcFactory = () => { let siteParser; const parsedUrl = new URL(window.location.href); @@ -48,61 +54,80 @@ const funcFactory = () => { } return { + foundMatch: foundMatch, readDomainOwnerAndProject: siteParser.readDomainOwnerAndProject, readBranch: siteParser.readBranch }; }; + function trackTime(keyPromise) { - const {readDomainOwnerAndProject, readBranch} = funcFactory(); - const {entity, owner, project} = readDomainOwnerAndProject(); - const branch = readBranch(); - let havenOnlyScrolledInCurrentInterval = false; - - function scrollHandler() { - havenOnlyScrolledInCurrentInterval = true; - } - - window.setInterval(function() { - if (havenOnlyScrolledInCurrentInterval) { - sendHeartbeat(preparePayload(entity, "app", project, branch, false)); - havenOnlyScrolledInCurrentInterval = false; + const { + readDomainOwnerAndProject, + readBranch + } = funcFactory(); + const { + entity, + owner, + project + } = readDomainOwnerAndProject(); + const branch = readBranch(); + let havenOnlyScrolledInCurrentInterval = false; + + function scrollHandler() { + havenOnlyScrolledInCurrentInterval = true; } - }, 30000); - function preparePayload(entity, type, project, branch, is_write) { - return { - entity: entity, - type: type, - time: new Date().getTime()/1000, - project: project, - branch: branch, - is_write: is_write, - editor: entity - }; - } + window.setInterval(function() { + if (havenOnlyScrolledInCurrentInterval) { + sendHeartbeat(preparePayload(entity, "app", project, branch, false)); + havenOnlyScrolledInCurrentInterval = false; + } + }, 30000); + + function preparePayload(entity, type, project, branch, is_write) { + return { + entity: entity, + type: type, + time: new Date().getTime() / 1000, + project: project, + branch: branch, + is_write: is_write, + editor: entity + }; + } + function sendHeartbeat(payload) { + let xhr = new XMLHttpRequest(); + xhr.open("POST", `https://wakatime.com/api/v1/users/current/heartbeats?api_key\=${keyPromise.key}`); + xhr.setRequestHeader("Content-Type", "application/json"); + xhr.send(JSON.stringify(payload)); + } - function sendHeartbeat(payload) { - let xhr = new XMLHttpRequest(); - xhr.open("POST", `https://wakatime.com/api/v1/users/current/heartbeats?api_key\=${keyPromise.key}`); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.send(JSON.stringify(payload)); - }; + function clickHandler() { + let payload = preparePayload(entity, "app", project, branch, true); + sendHeartbeat(payload); + havenOnlyScrolledInCurrentInterval = false; + } - function clickHandler() { - let payload = preparePayload(entity, "app", project, branch, true); - sendHeartbeat(payload); - havenOnlyScrolledInCurrentInterval = false; - } + window.onscroll = scrollHandler; + document.onclick = clickHandler; +} - window.onscroll = scrollHandler; - document.onclick = clickHandler; -}; function keyNotProvided(error) { - console.log("You should first configure this plugin by providing wakatime key"); + console.log("You should first configure this plugin by providing wakatime key"); } -let key = browser.storage.local.get("key"); -key.then(trackTime, keyNotProvided); + +const isSiteSupported = (url) => { + return supportedSites.some(el => { + el.siteMatch(url); + }); +}; + + +if (isSiteSupported(window.location.href)) { + let key = browser.storage.local.get("key"); + key.then(trackTime, keyNotProvided); +} From 8c86b65a89a5351a6cde52f224e5fb79712669d1 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Tue, 5 Dec 2017 22:10:44 +0100 Subject: [PATCH 6/7] Add siteMatch function, isSiteSupported does not function correctly --- wakatime-review.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/wakatime-review.js b/wakatime-review.js index 02269b0..b5af508 100644 --- a/wakatime-review.js +++ b/wakatime-review.js @@ -14,7 +14,10 @@ const bitbucket = { }; }, // site support function - siteMatch: (url) => {} + siteMatch: (url) => { + const parsedUrl = new URL(url); + return parsedUrl.host == 'bitbucket.org'; + } }; @@ -36,7 +39,10 @@ const stash = { project: grabAfter(splitUrl, 'repos') }; }, - siteMatch: (url) => {} + siteMatch: (url) => { + const parsedUrl = new URL(url); + return parsedUrl.host.includes('stash'); + } }; @@ -121,7 +127,7 @@ function keyNotProvided(error) { const isSiteSupported = (url) => { - return supportedSites.some(el => { + return supportedSites.some((el, index, array) => { el.siteMatch(url); }); }; From 71cf51f18fefae80962a1e0e8c21bd5eeeec46c9 Mon Sep 17 00:00:00 2001 From: Michal Klich Date: Wed, 6 Dec 2017 23:34:16 +0100 Subject: [PATCH 7/7] Add domain guard. --- wakatime-review.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/wakatime-review.js b/wakatime-review.js index b5af508..98344bc 100644 --- a/wakatime-review.js +++ b/wakatime-review.js @@ -68,6 +68,11 @@ const funcFactory = () => { function trackTime(keyPromise) { + + if (isSiteSupported(window.location.href)) { + return; + } + const { readDomainOwnerAndProject, readBranch @@ -128,12 +133,13 @@ function keyNotProvided(error) { const isSiteSupported = (url) => { return supportedSites.some((el, index, array) => { - el.siteMatch(url); + if (el.siteMatch(url)) { + return true; + } + return false; }); }; -if (isSiteSupported(window.location.href)) { - let key = browser.storage.local.get("key"); - key.then(trackTime, keyNotProvided); -} +let key = browser.storage.local.get("key"); +key.then(trackTime, keyNotProvided);