Created
August 22, 2014 14:58
-
-
Save bowmande/9c6421b035df13dcd2cf to your computer and use it in GitHub Desktop.
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 Add Points to Jira Board | |
// @namespace http://use.i.E.your.homepage/ | |
// @version 0.1 | |
// @description enter something useful | |
// @match http://tampermonkey.net/index.php?version=3.8.52&ext=dhdg&updated=true | |
// @copyright 2012+, You | |
// ==/UserScript== | |
// see https://jira.atlassian.com/browse/GHS-6755 | |
// | |
// CHANGELOG: | |
// V1.2 (2014-07-09): | |
// - also display total number of story points per stream | |
// - also update stories with no storypoints ('0 SP') | |
// V1.1 (2014-03-06): | |
// - also update empty columns ('0 SP') | |
// V1.0 (2013-07-02): | |
// - instead of periodically updating the SPs, use GreenHopper's 'workModeUIReady' event | |
// V0.3 (2013-05-01): | |
// - fetch more results when there are more User Stories than our max-results (500) | |
// V0.2 (2013-03-21): | |
// - fetch all issues at once per column (instead of per user story; saves a lot of REST calls) | |
// V0.1 (2013-02-26): | |
// - initial version | |
function processSPs() { | |
try { | |
var spByIssueId = {}; | |
// fieldId of field containing user story points | |
var SP_FIELD = "customfield_10004"; | |
var restApiBaseUrl = document.location.protocol+"//"+document.location.host; | |
if (GH.Ajax.CONTEXT_PATH && GH.Ajax.CONTEXT_PATH.length>0) { | |
restApiBaseUrl += "/"+GH.Ajax.CONTEXT_PATH; | |
} | |
// function is perform a 'GET' REST call | |
function getJson(restUrl, callback, callbackError) { | |
return jQuery.ajax({ | |
type: "GET", | |
url: restUrl, | |
success: callback, | |
dataType: "json", | |
contentType: "application/json; charset=utf-8", | |
error: callbackError | |
}); | |
} | |
// function which displays the specified story points inside its own span inside the specified container | |
function setSPSpanValue(jQContainers, sp) { | |
jQuery.each(jQContainers, function() { | |
jQContainer = jQuery(this); | |
var spDiv = jQContainer.find(".sp-flag"); | |
if (spDiv.length===0) { | |
spDiv = jQuery("<span class='sp-flag' style='margin-left: 5px; font-weight: bold'></span>").appendTo(jQContainer); | |
} | |
spDiv.html("("+sp+" SP)"); | |
}); | |
} | |
jQuery("#ghx-board-name").css("display", "inline"); | |
function processColumn(boardInfo, columnInfo) { | |
var statusIds = columnInfo.statusIds; | |
// collect all issue keys of the current column | |
var issueKeys = _.map(boardInfo.issuesData.issues, function(issueData) { | |
if (jQuery.inArray(String(issueData.statusId), statusIds)!==-1) { | |
return issueData.key; | |
} | |
return null; | |
}); | |
issueKeys = _.without(issueKeys, null); | |
return searchIssues(issueKeys, columnInfo.id, 0, 0); | |
} | |
var grandTotalSP = 0; | |
function searchIssues(issueKeys, dataId, startAt, totalSP, deferred) { | |
if (!deferred) { | |
deferred = jQuery.Deferred(); | |
} | |
var jQHeader = jQuery(".ghx-column-headers li[data-id="+dataId+"] h2"); | |
jQHeader.css("display", "inline"); | |
if (issueKeys.length==0) { | |
setSPSpanValue(jQHeader, 0); | |
return deferred.resolve(); | |
} | |
var url = restApiBaseUrl+"/rest/api/2/search?jql=key in ("+issueKeys+")&fields="+SP_FIELD+"&maxResults=500"; | |
getJson(url+"&startAt="+startAt, function(searchResult) { | |
jQuery.each(searchResult.issues, function(i, issue) { | |
if (issue.fields && issue.fields[SP_FIELD]!=null) { | |
var sp = issue.fields[SP_FIELD]; | |
setSPSpanValue(jQuery(".ghx-issue[data-issue-key='"+issue.key+"'] .ghx-key"), sp); | |
spByIssueId[issue.id] = sp; | |
totalSP += sp; | |
totalSP = Math.round(totalSP*100)/100; | |
} | |
}); | |
setSPSpanValue(jQHeader, totalSP); | |
grandTotalSP += totalSP; | |
grandTotalSP = Math.round(grandTotalSP*100)/100; | |
var boardTitle = jQuery("#ghx-view-selector"); | |
setSPSpanValue(boardTitle, grandTotalSP); | |
var callStartAt = searchResult.startAt||0; | |
if (startAt+searchResult.issues.length < searchResult.total) { | |
searchIssues(issueKeys, dataId, startAt+searchResult.maxResults, totalSP, deferred); | |
} | |
else { | |
deferred.resolve(); | |
} | |
}); | |
return deferred; | |
} | |
var rapidViewId = GH.RapidBoard.State.data.rapidViewId; | |
if (rapidViewId) { | |
var url = restApiBaseUrl+GH.Ajax.REST_URL_BASE+"/xboard/work/allData/?rapidViewId="+rapidViewId; | |
getJson(url, function(boardInfo) { | |
var promises = []; | |
var i; | |
for (i=0; i<boardInfo.columnsData.columns.length; i++) { | |
var columnInfo = boardInfo.columnsData.columns[i]; | |
var deferred = processColumn(boardInfo, columnInfo); | |
promises.push(deferred); | |
} | |
var swimlanes = boardInfo.swimlanesData[boardInfo.swimlanesData.swimlaneStrategy+"SwimlanesData"].swimlanes; | |
jQuery.when.apply(jQuery, promises).done(function() { | |
for (i=0; i<swimlanes.length; i++) { | |
var swimlane = swimlanes[i]; | |
var totalSP = 0; | |
// update columns and the stories in the columns | |
var j; | |
for (j=0; j<swimlane.issueIds.length; j++) { | |
var issueId = swimlane.issueIds[j]; | |
var sp = spByIssueId[issueId+""]; | |
if (sp) { | |
totalSP += sp; | |
} | |
} | |
// update swimlane total sps | |
var $swimlaneDiv = jQuery(".ghx-swimlane-header[data-swimlane-id="+swimlane.id+"] .ghx-heading"); | |
totalSP = Math.round(totalSP*100)/100; | |
setSPSpanValue($swimlaneDiv, totalSP); | |
} | |
}); | |
}); | |
} | |
} | |
catch (e) { | |
console.log("processSPs error occured", e); | |
} | |
} | |
jQuery().ready(function() { | |
AJS.$(GH).bind('workModeUIReady', function() { | |
processSPs(); | |
}); | |
}); |
Hi @lukasrossa,
I was facing the same issue and was able to get the information with jQuery._data( AJS.$(GH).get(0), "events" );
Unfortunately these events get not triggered when viewing the Backlog...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, how did you discover the 'workModeUIReady' event? I'm trying to find out more information about the events the RapidBoard sends but am having little luck.