// // Create readable table with scope changes of a JIRA Version/Release/Fix Version // The existing graph is nice, but hard to read the details // // Known bug: you have to refresh the page after first load and after selecting another version in the dropdown // // get parameters from url let searchParams = new URLSearchParams(window.location.search) let versionId = searchParams.get('version') let rapidViewId = searchParams.get('rapidView') // Get numerical part of issuekey // Split issuekey at dash (-). So ABC-123 becomes ABC and Id 123 and returns Id function GetIdOfIssueKey(issuekey) { aIssueKeyParts = issuekey.split("-"); return aIssueKeyParts[1]; } $.getJSON( "../rest/greenhopper/1.0/rapid/charts/versionreport?rapidViewId=" + rapidViewId + "&versionId=" + versionId, function( data ) { // First gather some general data of all stories in selected Version var storyData = []; // get all information (title, SPs) of all incompleted issues var incompleteEstimatedIssues = data.contents.incompleteEstimatedIssues; $.each( incompleteEstimatedIssues, function( key, value ) { keyId = GetIdOfIssueKey(value.key); storyData[keyId] = value.summary; }); // get all information (title, SPs) of all completed issues var completedIssues = data.contents.completedIssues; //console.log(data.contents.completedIssues); $.each( completedIssues, function( key, value ) { keyId = GetIdOfIssueKey(value.key); storyData[keyId] = value.summary; }); // get all information (title, SPs) of all incompleteUnestimatedIssues issues var incompleteUnestimatedIssues = data.contents.incompleteUnestimatedIssues; $.each( incompleteUnestimatedIssues, function( key, value ) { keyId = GetIdOfIssueKey(value.key); storyData[keyId] = value.summary; }); // Then: get change-entries of Version GetChanges(storyData); }); // does not work yet: table needs up update if otheh Version is selected $( "#ghx-dropdown-trigger, #ghx-chart-picker, #ghx-chart-picker-form, .ghx-controls" ).change(function() { console.log('change'); alert('change'); GetChanges(storyData); }); /** * Get title of story and add it to html-element * */ function GetIssueInfo (storyId, rapidViewId, thisobj) { // get story information $.getJSON( "../rest/greenhopper/1.0/xboard/issue/details.json?rapidViewId=" + rapidViewId + "&issueIdOrKey=" + storyId, function( data ) { // get SPs if (data) { storySP = data.tabs.defaultTabs[0].fields[2].value; title = data.tabs.defaultTabs[0].fields[0].text + ' (' + storySP + ')'; $(thisobj).text(title); } }); } function GetChanges (storyData) { // get changes of Version $.getJSON( "../rest/greenhopper/1.0/rapid/charts/versionprogresschart?rapidViewId=" + rapidViewId + "&versionId=" + versionId, function( data ) { // get changes changes = data.changes; var lastDate, lastStoryKey, lastStoryTitle; var aaDateStory = {}; var aLastKnownSp = {}; var rows = ""; var sub = ''; var rowClass = ''; var filterLink = ''; // loop all changes $.each( changes, function( key, value ) { filterLink = ''; var changeEntry = value[0]; // make human readable keyId = parseInt(changeEntry.key.substr(4, 20)); var tskey = parseInt(key); var ts = new Date(tskey); //console.log(ts); var y = ts.getFullYear(); var m = ts.getMonth(); m += 1; // JavaScript months are 0-11 if (m < 10) { m = "0" + m; } var d = ts.getDate(); if (d < 10) { d = "0" + d; } var h = ts.getHours(); if (h < 10) { h = "0" + h; } var min = ts.getMinutes(); if (min < 10) { min = "0" + min; } date = y + "-"+ m + "-"+ d; time = h + ":"+ min ; // + ":"+ ts.getSeconds() var content = 0; // tracks if there is valuable content in this changeEntry var addedOrRemoved = ''; if (changeEntry.added === true) { addedOrRemoved = 'added'; // added to this version content++; } else if (changeEntry.added === false) { addedOrRemoved = 'removed '; //removed from this version content++; } else { addedOrRemoved = ''; // like: a changed story that was not added of removed } var spChange = ''; var diff = ''; var storyKey = changeEntry.key; // a change with statc filled has a changed amount of SP if (changeEntry.statC && Object.keys(changeEntry.statC).length > 0) { var old; var iDiff; var newSP; var sign = ""; if (changeEntry.statC.newValue) { newSP = changeEntry.statC.newValue; aLastKnownSp[storyKey] = newSP; diff = "(+" + newSP + ")"; } else { // items witout a statC.newValue can be skipped return true; } //console.log(value[0].statC); // if (changeEntry.statC.oldValue) { old = changeEntry.statC.oldValue; iDiff = changeEntry.statC.newValue - changeEntry.statC.oldValue; if (iDiff > 0 ) { sign = '+'; } diff = "(" + sign + iDiff + ")"; } else { old = "-"; } spChange = '' + old + ' -> ' + newSP + ''; content++; } else { if (aLastKnownSp[storyKey]) { spChange = '' + aLastKnownSp[storyKey] + ''; } else { spChange = ' '; } } // skip if not usefull content, like ???? if (content == 0) return true; storyTitle = storyData[keyId]; var storyKeyDisp, storyTitleDisp, dateDisp; // hide showing date if its the same date as previous change if (lastDate == date) { dateDisp = '' + date + ''; } else { dateDisp = date; } // hide showing storyKey if its the same story as previous change if (lastStoryKey == storyKey) { storyKeyDisp = '' + storyKey + ''; } else { storyKeyDisp = '' + storyKey + ''; filterLink = ' +'; } sub = false; rowClass = ''; if (lastStoryKey == storyKey && lastDate == date) { sub = true; rowClass = 'class="vrp-subentry"' //time = ''; } // hide title if the same as previous row if (lastStoryTitle == storyTitle) { storyTitleDisp = '-'; // n/a if title is unavilable (like when issue is currently not part of Version) } else if (!storyTitle) { storyTitleDisp = 'n/a (click to load)'; } else { storyTitleDisp = storyTitle; } // build table rows += '' + dateDisp + '' + time + '' + addedOrRemoved + '' + spChange + '' + diff + '' + storyKeyDisp + filterLink + '' + storyTitleDisp + '' /*+ ''+ JSON.stringify(value[0].statC)+''*/+''; // try to combine changes of same story with same minute (like: an add + a SP change) if (keyId < 10000){ sKeyId = "0"+ keyId; } else { sKeyId = keyId; } var sArrayKey = y+""+m+""+d+""+sKeyId; // y+""+m+""+d+""+h+""+min+""+keyId; var arrayKey = sArrayKey.toString(); // Story all data in one big array to be processed later for merging/combining data if (!aaDateStory[arrayKey]) aaDateStory[arrayKey] = {}; if (!aaDateStory[arrayKey].combined) aaDateStory[arrayKey].combined = 0; aaDateStory[arrayKey].date = date; aaDateStory[arrayKey].time = time; aaDateStory[arrayKey].storyKey = storyKey; aaDateStory[arrayKey].title = storyTitle; aaDateStory[arrayKey].combined++; // count how much events are combined to one if (changeEntry.added) aaDateStory[arrayKey].addedOrRemoved = addedOrRemoved; if (value[0].statC) { if (changeEntry.statC.newValue) { aaDateStory[arrayKey].newValue = changeEntry.statC.newValue; // if newValue but no oldValue: oldValue is 0 if (!changeEntry.statC.oldValue) { changeEntry.statC.oldValue = "0"; aaDateStory[arrayKey].oldValue = "0"; } } // keep first oldValue: dont overwrite with new oldValue: 2->5 + 5->3 should be 2-> 4 if (changeEntry.statC.oldValue && aaDateStory[arrayKey].oldValue != "") { aaDateStory[arrayKey].oldValue = changeEntry.statC.oldValue; } } lastStoryKey = storyKey; if (storyTitle) { lastStoryTitle = storyTitle; } else { lastStoryTitle = Math.random(); } lastDate = date; // ' + JSON.stringify(value[0].statC) + ' }); /*console.log(aaDateStory); rows += '----'; $.each( aaDateStory, function( key, value ) { if (!value) return true; if (value.oldValue) { oldValueDisp = value.oldValue; } else { oldValueDisp = ""; } if (value.newValue) { newValueDisp = value.newValue; } else { newValueDisp = ""; } if (value.addedOrRemoved) { addedOrRemovedDisp = value.addedOrRemoved; } else { addedOrRemovedDisp = ""; } rows += '' + value.date + '' + value.time + '' + addedOrRemovedDisp + '' + oldValueDisp + '' + newValueDisp + '' + value.storyKey + '' + value.title + '' + value.combined + 'x'; });*/ var headerrow = 'DateTimeAdd/Rem.SP changeKeySummary'; $("#ghx-report-content").prepend('' + headerrow + rows + '
'); // Add Search/filter $(".vrp-search").on("keyup", function() { //$(".vrp-search").width("600px"); var value = $(this).val().toLowerCase(); $(".vrp-table tr").filter(function() { $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) }); }); // Insert Issuekey in Search/filter $(".vrp-populateSearch").on("click", function() { keyid = $(this).data('keyid'); $(".vrp-search").val(keyid).focus().click().keyup(); }); // Get title $(".vrp-nadata").on("click", function() { $(this).text('loading title...'); keyid = $(this).data('keyid'); GetIssueInfo(keyid, rapidViewId, this); }); }); }