Last active
January 27, 2023 11:29
-
-
Save ErgEnn/6fd34add5aa1d6bfdd0f1b634b93a77e to your computer and use it in GitHub Desktop.
Shows total time of Jira ticket based on Toggl(client side only).
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
// ==UserScript== | |
// @name JiraTogglTotalTime | |
// @namespace https://gist.github.com/ErgEnn/6fd34add5aa1d6bfdd0f1b634b93a77e | |
// @version 0.3 | |
// @description Shows total time of Jira ticket based on Toggl(client side only). Requires Toggl task descr to contain the ticket key. | |
// @author Ergo Enn | |
// @match https://*/browse* | |
// @match https://*/jira/software* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=atlassian.net | |
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js | |
// @downloadURL https://gist.github.com/ErgEnn/6fd34add5aa1d6bfdd0f1b634b93a77e/raw/1067d304ce3c614ac829efc637de4c9d109a332b/jiraTogglTotalTime.user.js | |
// @updateURL https://gist.github.com/ErgEnn/6fd34add5aa1d6bfdd0f1b634b93a77e/raw/1067d304ce3c614ac829efc637de4c9d109a332b/jiraTogglTotalTime.user.js | |
// @grant GM.xmlHttpRequest | |
// @grant GM.getValue | |
// @grant GM.setValue | |
// ==/UserScript== | |
(async () => { | |
let togglToken = await GM.getValue("togglToken") | |
let togglWorkspaceId = await GM.getValue("togglWorkspaceId") | |
if(!togglToken){ | |
GM.setValue("togglToken",prompt("API TOKEN REQUIRED. log in to track.toggl.com. From sidebar -> Profile -> Profile settings -> API Token")) | |
GM.setValue("togglWorkspaceId",prompt("WORKSPACE ID REQUIRED. log in to track.toggl.com. From sidebar -> click Team -> click your team name -> copy the id from url: ...workspaces/{id}/members")) | |
togglToken = await GM.getValue("togglToken") | |
togglWorkspaceId = await GM.getValue("togglWorkspaceId") | |
} | |
let upperDate = "2023-01-01" //TODO: Make request upper date limit dynamic | |
//TODO: Show notification when tracked time approaches or surpasses the estimation | |
var $j = jQuery.noConflict(true); | |
function toHMS(totalMilliSeconds){ | |
var totalSeconds = totalMilliSeconds / 1000; | |
var hours = Math.floor(totalSeconds / 3600); | |
totalSeconds %= 3600; | |
var minutes = Math.floor(totalSeconds / 60); | |
var seconds = Math.floor(totalSeconds % 60); | |
return `${String(hours).padStart(2,'0')}h${String(minutes).padStart(2,'0')}m${String(seconds).padStart(2,'0')}s`; | |
} | |
var currentRefresher = 0; | |
function refreshTimeField(ticketNum){ | |
var timeField = $j('*[data-testid="issue.views.issue-base.context.time-tracking.value"] small').children().first(); | |
if(timeField.is(":visible")){ | |
console.log("refreshing data for ticket "+ticketNum) | |
var historic = 0; | |
var current = 0; | |
GM.xmlHttpRequest({ | |
method: "GET", | |
url: `https://api.track.toggl.com/reports/api/v2/summary?user_agent=ErgoEnnTogglJira&workspace_id=${togglWorkspaceId}&description=${ticketNum}&since=${upperDate}`, | |
headers: { | |
"Authorization": "Basic " + btoa(`${togglToken}:api_token`) | |
}, | |
onload: function(response) { | |
var data = JSON.parse(response.responseText); | |
historic = data.data[0].time; | |
timeField.text(toHMS(historic+current)) | |
} | |
}); | |
GM.xmlHttpRequest({ | |
method: "GET", | |
url: "https://api.track.toggl.com/api/v8/time_entries/current", | |
headers: { | |
"Authorization": "Basic " + btoa(`${togglToken}:api_token`) | |
}, | |
onload: function(response) { | |
var data = JSON.parse(response.responseText); | |
var startTime = new Date(data.data.start).getTime(); | |
if(currentRefresher) | |
window.clearInterval(currentRefresher); | |
if(data.data.description.startsWith(ticketNum)){ | |
currentRefresher = window.setInterval(function(){ | |
current = ((new Date()).getTime() - startTime) | |
timeField.text(toHMS(historic+current)) | |
},100) | |
}else{ | |
current = 0; | |
} | |
} | |
}); | |
return true; | |
} | |
return false; | |
} | |
var refresher=0; | |
$j(document).ready(function () { | |
var prevTicketNum = 0; | |
var initialLoadDone = true; | |
$j( "body" ).bind("DOMSubtreeModified", function(){ | |
var ticketNum = $j('*[data-testid="issue.views.issue-base.foundation.breadcrumbs.current-issue.item"]').first().text(); | |
if(ticketNum){ | |
if(!initialLoadDone){ | |
initialLoadDone = refreshTimeField(ticketNum); | |
} | |
if(prevTicketNum != ticketNum){ | |
console.log("ticket changed from "+prevTicketNum+" to "+ticketNum) | |
prevTicketNum = ticketNum; | |
if (refresher) | |
window.clearInterval(refresher); | |
initialLoadDone = false; | |
refresher = window.setInterval(function(){refreshTimeField(ticketNum)},60000) | |
} | |
}else{ | |
prevTicketNum = 0 | |
if (refresher) | |
window.clearInterval(refresher); | |
} | |
}); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Had isssue with:
To get popup you need to expand "More fields" tab under Jira ticket.
Otherwise LGTM