NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name ColoredLabels // @namespace LucasRollan // @description Use story labels to create a visual representation of stories status in Jira // @include https://jira.swacorp.com/plugins/servlet/gadgets/ifr?* // @include https://jira.swab2bqa.com/plugins/servlet/gadgets/ifr?* // @include https://jira.swacorp.com/secure/Dashboard.jspa* // @include https://jira.swab2bqa.com/secure/Dashboard.jspa* // @grant none // @version 3.00 // ==/UserScript== /*** CONFIG VARIABLES ***/ var labelsConfig = { // Script defaults | Jira defaults showEmptyLabels: false, // false | false showLabelsColumn: false, // false | false collapseHighLevelPointEstimate: true, // true | false collapseFinalPointEstimate: true, // true | false showTotalPointsEstimate: true // true | false }; /*** Script Definition ***/ labelsConfig.getTextDefinition = function() { var text = 'var labelsConfig = {\n'; for (var property in this) { if (typeof labelsConfig[property] != 'function') { text += ' '+ property +': '+ labelsConfig[property] + ',\n'; } } text = text.substring(0, text.length - 2); text += '\n}'; return text; }; var ColoredLabels = {}; ColoredLabels.injectCode = function(code) { this.inject('script', 'text/javascript', code); }; ColoredLabels.injectCSS = function(code) { this.inject('style', 'text/css', code); }; ColoredLabels.inject = function(tag, type, code) { var head = document.getElementsByTagName('head')[0]; var obj = document.createElement(tag); obj.type = type; obj.innerHTML = code; head.appendChild(obj); }; ColoredLabels.getFunctionListCode = function(nameList) { var code = ''; for (var i in nameList) { code += this.getFunctionCode(nameList[i]); } return code; }; ColoredLabels.getFunctionCode = function(name) { var code = 'var '+ name +' = ' + this[name].toString() + ';\n'; return code; }; ColoredLabels.createLabels = function() { var $ = jQuery; var people = { "AA": "Alfonsina Altamira", "AR": "Ahsan Raza", "CF": "Cheryl Fisk", "DA": "Daniel Aguilera", "DJ": "Daniela Jacquelin", "MT": "Marcos Torres", "RB": "Romina Bianucci", "AE": "Alexis Escudero", "CU": "Cristian Urbano", "ES": "Emiliano Santi", "EE": "Emmanuel Elmoni", "EZ": "Ezequiel Von Ziegler", "FG": "Flavia Gramajo", "GZ": "Gonzalo Zunino", "HS": "Hernan Seghetti", "JB": "Javier Baccarelli", "JD": "Julio Danni", "KP": "Kevin Prox", "MER": "Mariano Remedi", "MAR": "Martin Rodriguez", "NS": "Nicolas Siandro", "QC": "Qaiser Chaudhry", "ZW": "Zane Wu", "AB": "Agustina Bosso", "AF": "Ariel Fonseca", "GB": "Gisele Brizuela", "IF": "Ivana Fenoglio", "LR": "Lucas Rodriguez", "SG": "Silvia Garcia" }; var CSS = '.ColoredLabel {\n'; CSS += ' height: 20px;\n'; CSS += ' border: solid 1px gray;\n'; CSS += ' border-radius: 5px;\n'; CSS += ' font-weight: bold;\n'; CSS += ' text-align: center;\n'; CSS += ' line-height: 20px;\n'; CSS += ' font-family: arial,sans-serif;\n'; CSS += ' font-size: 12px;\n'; CSS += ' cursor: default;\n'; CSS += '}\n'; CSS += '.RED {\n'; CSS += ' background-color: red;\n'; CSS += ' color: white;\n'; CSS += '}\n'; CSS += '.YELLOW {\n'; CSS += ' background-color: yellow;\n'; CSS += ' color: black;\n'; CSS += '}\n'; CSS += '.GREEN {\n'; CSS += ' background-color: green;\n'; CSS += ' color: white;\n'; CSS += '}\n'; injectCSS(CSS); var divTemplate = '<div title="{TITLE}" class="ColoredLabel {COLOR}">{CONTENT}</div>'; var rowTemplate = '<td class="nav">{DIV}</td>'; addColoredLabelsTableHeaders(); function addColoredLabelsTableHeaders() { $('tr.rowHeader>th[rel^="labels"]').after('<th>BA</th><th>DEV</th><th>QC</th>'); }; if (!labelsConfig.showLabelsColumn) { hideLabelsColumn(); } function hideLabelsColumn() { $('tr.rowHeader>th[rel^="labels"]').hide(); }; if (labelsConfig.collapseHighLevelPointEstimate) { replaceHlpeText(); } function replaceHlpeText() { $('span[title="Sort By High Level Points Estimate"]').text('HLPE'); }; if (labelsConfig.collapseFinalPointEstimate) { replaceFpeText(); } function replaceFpeText() { $('span[title="Sort By Final Points Estimate"]').text('FPE'); }; if (labelsConfig.showTotalPointsEstimate) { if (fpeExists()) { showTotalFpe(); } else { showTotalHlpe(); } } function totalPointsInit() { $('.aui-group.count-pagination').css('margin-top','-28px'); } function fpeExists () { return $('th span').index($('[title="Sort By Final Points Estimate"]')) != -1; } function showTotalFpe() { var index = getFpeIndex(); var count = sumEstimates(index); var numCells = countColumns(); if (count) { totalPointsInit(); $('table').append(createTotalsRow(numCells, count, index)); } }; function getFpeIndex () { return $('th span').index($('[title="Sort By Final Points Estimate"]')); }; function showTotalHlpe() { var index = getHlpeIndex(); var count = sumEstimates(index); var numCells = countColumns(); if (count) { totalPointsInit(); $('table').append(createTotalsRow(numCells, count, index)); } }; function getHlpeIndex () { return $('th span').index($('[title="Sort By High Level Points Estimate"]')); }; function sumEstimates (pos) { var count = 0; $('tr').each(function(){count += $(this).children('td:eq('+ pos +')').text()*1;}); return count; }; function countColumns () { return $('tr:eq(1)>td').length; }; function createTotalsRow (numCells, total, position) { var row = $('<tr></tr>'); for (var i = 0; i < numCells; i++) { var cell = $('<td></td>'); if (i == position) { cell.html('<b>'+total+'</b>'); } else if (i == position-1) { cell.css('text-align','right'); cell.html('<b>Total</b>'); } row.append(cell); } return row; }; $('td.labels').each( function(){ var availableLabels = ['BA','DEV','QC']; // < label categories var labels = {}; for (var key in availableLabels) { labels[availableLabels[key]] = {color:'', content:'', title:''}; // < label properties } //e.g. availableLabels['BA'].color //To add new labels this is the place ^ $(this).children('div').children('ul').children('li').each( //each label function() { var inner = $(this).html(); for (var type in labels) { //parse each type var regex = new RegExp(type + '\\.(\\w+)(?:\\.(\\w{1,3}))?'); //{TYPE}.{COLOR}.{INITIALS} -> e.g. DEV.GREEN.LR // [2 or 3 initials] var results = inner.match(regex); if (results) { //matches labels[type].color = results[1]; labels[type].content = results[2] || ''; labels[type].title = people[labels[type].content] || ''; $(this).hide(); } } } ); var insert = ''; for (var type in labels) { var currentDiv = divTemplate; if (labelsConfig.showEmptyLabels || (labels[type].color !== '')) { for (var property in labels[type]) { currentDiv = currentDiv.replace('{'+ property.toUpperCase() +'}', labels[type][property]); } } else { currentDiv = ''; } insert += rowTemplate.replace('{DIV}', currentDiv); } $(this).after(insert); if (!labelsConfig.showLabelsColumn) { $(this).hide(); } } ); requestSetHeight($('table#issuetable').parent().height()); }; ColoredLabels.requestSetHeight = function(size) { parent.setIframeHeight(size, location.href); } ColoredLabels.setIframeHeight = function(size, url) { var $ = jQuery; var iframeId = $('iframe[src="'+ url +'"]').height(size).attr('id'); var containerId = iframeId.replace('gadget','rep'); $('#'+ containerId).height(size + 32); refreshPositions(); function refreshPositions() { $('li[id^="rep-"].gadget').each(function(){ var boxId = $(this).attr('id').replace('rep','gadget') + '-renderbox'; $('#'+ boxId).css('top', $(this).position().top); }); } //gadget-30424 //rep-30424 //gadget-30424-renderbox } ColoredLabels.waitForPageLoad = function() { $ = jQuery; var table = document.getElementById('issuetable'); if (table) { if (!$('#issuetable').hasClass('ColoredLabelsStarted')) { $('#issuetable').addClass('ColoredLabelsStarted'); createLabels(); } } }; ColoredLabels.setTimer = function() { timeInterval = setInterval(waitForPageLoad, 1 * 1000); }; if (location.pathname == '/secure/Dashboard.jspa') { code = ColoredLabels.getFunctionCode('setIframeHeight'); } else { code = ColoredLabels.getFunctionListCode(['injectCSS','inject', 'createLabels', 'requestSetHeight', 'waitForPageLoad', 'setTimer'])+ labelsConfig.getTextDefinition() +';\n setTimer();'; } ColoredLabels.injectCode(code);