Last active
February 17, 2021 12:54
-
-
Save rayburgemeestre/e2a4ed179d0820c0e8d4 to your computer and use it in GitHub Desktop.
Tampermonkey jira priority
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 Visualize issue ranks in the Jira Agile board | |
// @namespace http://cppse.nl | |
// @version 2.3.4.3 | |
// @description It will search for the ranks using an Ajax Jira API call with two seconds in between | |
// and update the board with colored rank indicators. | |
// @author Ray Burgemeetre | |
// @match https://*/secure/RapidBoard.jspa* | |
// @updateURL http://cppse.nl/public/tampermonkey_agile_board_prios-meta.js | |
// @downloadURL http://cppse.nl/public/tampermonkey_agile_board_prios.js | |
// @grant none | |
// ==/UserScript== | |
(function () { | |
// Configuration | |
var // The JQL for fetching the ranks | |
jql = "sprint in openSprints() and status != 'Done' AND type not in (Sub-task) order by Rank", | |
// First four colors are shades of green.. (after that, stuff fades from grey to red) | |
colors = [green(0), green(1), green(2), green(3)]; | |
// Just for my convenience | |
if (window.location.href.match(/brightcomputing/)) { | |
jql = "sprint in openSprints() and status not in ('Done', 'Resolved', 'Closed') AND type not in (Sub-task) AND project in ('Cluster Manager', 'Master Installer', 'Miscellaneous') AND labels in (bigdata,hadoop, spark) order by Rank" | |
} | |
function updateRanksInBoard() | |
{ | |
var xmlhttp = new XMLHttpRequest(); | |
xmlhttp.onreadystatechange = function() { | |
if (xmlhttp.readyState != XMLHttpRequest.DONE) | |
return; | |
if (xmlhttp.status == 200) { | |
var ranks = {}, issues = document.querySelectorAll('.ghx-issue'), isSubTask, | |
key, color, rankBoxEl, rankEl, tmp; | |
// console.log(xmlhttp.responseText); | |
var response = JSON.parse(xmlhttp.responseText); | |
// Create lookup for ranks per issue key | |
for (var i in response['issues']) { | |
ranks[response['issues'][i]['key']] = parseInt(i) + 1; | |
} | |
// Visualize them in a small box for each issue | |
for (var i=0; i<issues.length; i++) { | |
key = issues[i].getAttribute('data-issue-key'); | |
isSubTask = issues[i].className.indexOf('ghx-issue-subtask') !== -1; | |
color = false; | |
// Visualize subtasks with the ranking of their parent | |
if (isSubTask) { | |
key = issues[i].parentNode.parentNode.getAttribute('data-issue-key'); | |
color = '#E8F5FF'; | |
} | |
if (!ranks[key]) | |
continue; | |
if (!color) { | |
tmp = Object.keys(response['issues']).length; | |
color = colors[ranks[key] - 1] || red(ranks[key] - colors.length - 1, tmp); | |
} | |
try { | |
// Ensure the "ghx-end" div exists, simply create it if it doesn't. | |
// (if issues have no estimates etc., this div isn't rendered) | |
if (!(tmp = issues[i].querySelector('.ghx-end'))) { | |
tmp = document.createElement('div'); | |
tmp.className = 'ghx-end'; | |
issues[i].appendChild(tmp); | |
} | |
// Create rank cornered indicator if it doesn't exist yet | |
rankEl = issues[i].querySelector('.ghx-end .my-rank'); | |
if (!rankEl) { | |
rankBoxEl = document.createElement('div'); | |
rankBoxEl.className = 'ghx-corner'; | |
rankEl = document.createElement('span'); | |
rankEl.className = 'aui-badge my-rank'; | |
rankBoxEl.appendChild(rankEl); | |
issues[i].querySelector('.ghx-end').appendChild(rankBoxEl); | |
} | |
// Populate indicator | |
rankEl.style.backgroundColor = color; | |
rankEl.innerHTML = ranks[key]; | |
// Squeeze them to fit | |
tmp = issues[i].querySelector('.ghx-end').querySelectorAll('.ghx-corner'); | |
for (var j=0; j<tmp.length; j++) { | |
tmp[j].style.float = 'left'; | |
} | |
} | |
catch (e) { | |
console.log('DOM manipulation failed, ignoring exception (probably variant of Jira Board): ', e); | |
} | |
} | |
// Periodically update ranks | |
setTimeout(updateRanksInBoard, 2000); | |
} | |
else { | |
console.log(textStatus + " : " + errorThrown); | |
// Periodically update ranks | |
setTimeout(updateRanksInBoard, 2000); | |
} | |
} | |
xmlhttp.open("GET", "//" + window.location.host + "/rest/api/latest/search?jql=" + escape(jql), true); | |
xmlhttp.setRequestHeader('Content-type', 'application/json'); | |
xmlhttp.send(); | |
} | |
//window.addEventListener('DOMContentLoaded', updateRanksInBoard, false); | |
setTimeout(updateRanksInBoard, 3000); // somehow Jira messes up window.onload, and some other alternatives I tried... | |
// Utility functions | |
function green(level) | |
{ | |
// Starts at rgb(0, 255, 0) and fades to rgb(255, 255, 255) | |
function divideTimes(num, divide, times) | |
{ | |
if (!times) | |
return num; | |
--times; | |
if (!times) | |
return num / divide; | |
else | |
return divideTimes(num / divide, divide, times); | |
} | |
var c = Math.floor(255.0 - divideTimes(255, 2, level)); | |
return 'rgb(' + c + ', 255, ' + c + ')'; | |
} | |
function red(level, maxlevel) | |
{ | |
// Starts at rgb(237, 237, 237) and fades to rgb(255, 0, 0) | |
try { | |
var r = (((255 - 237) / maxlevel) * level) + 237, | |
g = 237 - (( 237 / maxlevel) * level), | |
b = 237 - (( 237 / maxlevel) * level); | |
return 'rgb(' + Math.floor(r) + ', ' + Math.floor(g) + ', ' + Math.floor(b) + ')'; | |
} | |
catch (e) { return 'rgb(255, 0, 0)'; } | |
} | |
})(); |
FYI ->Actually, this fix apparently doesn't work in FF with grease monkey. I'll update you with further changes if I can find them.
Hi Kat, Thanks! I've refactored out the $.ajax() call, hopefully that will work better. Thanks :)
I also made it a little more generic/robust hopefully (and project independant, hope it still works for AutoTrack?) updating should be possible via Tampermonkey itself. I needed a few changes to get it to work on another Jira 😄
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Ray! I had to add a line to import jquery, because this script broke over here at AT. If you feel like updating it, add the following at ln 12:
// @require https://code.jquery.com/jquery-1.11.3.min.js