Skip to content

Instantly share code, notes, and snippets.

@davidfraser
Last active September 19, 2018 10:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidfraser/50797840fb645db61c4b154067249f5c to your computer and use it in GitHub Desktop.
Save davidfraser/50797840fb645db61c4b154067249f5c to your computer and use it in GitHub Desktop.
Some TamperMonkey scripts and bash scripting to make our daily standup report from JIRA
Daily Standup Report for JIRA
=============================
This project contains two tampermonkey scripts (for installation in Chrome),
and a bash script that makes it easier for us to quickly make the report we use at our daily standup meeting
// ==UserScript==
// @name GitLab - Hide/Show WIP Merge Requests
// @namespace http://tampermonkey.net/
// @version 0.1
// @description In GitLab Merge Requests pages, hide all the WIP items
// @author You
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @match https://gitlab.sjsoft.com/*/merge_requests*
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
function isWIP(mrChildNode) {
return mrChildNode.getElementsByClassName('merge-request-title-text')[0].innerText.indexOf('WIP') >= 0
}
function forTargetBranch(mrChildNode, whichBranch) {
var branch_targets = mrChildNode.getElementsByClassName('fa-code-fork');
if (whichBranch == '[default]') {
return branch_targets.length == 0
} else {
return (branch_targets.length >= 1 && branch_targets[0].nextSibling.textContent.trim() == whichBranch)
}
}
function updateDisplay() {
console.log("Updating list of merge requests: showWIP", showWIP, "targetBranch", targetBranch)
for (var mrItem of document.getElementsByClassName('mr-list')) {
for (var child of mrItem.children) {
if (!showWIP && isWIP(child)) {
child.style.display = 'none'
} else if (targetBranch && !forTargetBranch(child, targetBranch)) {
child.style.display = 'none'
} else {
child.style.display = 'block'
}
}
};
}
function setShowWIP(shouldShow) {
showWIP = shouldShow;
if (showWIP) {
sessionStorage.setItem('gitlab-x-mr-show-wip', 'true');
console.log("Showing merge requests");
} else {
sessionStorage.setItem('gitlab-x-mr-show-wip', 'false');
console.log("Hiding merge requests");
}
var styleSheet = document.getElementById('wip-filter-styles');
styleSheet.innerHTML = getWIPStyles();
}
function getWIPStyles() {
return 'div.wip-filter {padding: 7px; }\n' + (showWIP ? 'a#filter-show-wip' : 'a#filter-hide-wip') + ' { font-weight: bold; }';
}
function hideWIPMergeRequests() {
setShowWIP(false);
updateDisplay();
};
function showWIPMergeRequests() {
setShowWIP(true);
updateDisplay();
};
function showMergeRequestsByBranch(newTargetBranch) {
targetBranch = newTargetBranch || '';
console.log("Showing merge requests for branch", targetBranch);
sessionStorage.setItem('gitlab-x-mr-filter-branch', targetBranch);
var styleSheet = document.getElementById('branch-filter-styles');
styleSheet.innerHTML = getBranchStyles();
updateDisplay();
};
function getBranchStyles() {
var style = 'div.branch-filter {padding: 7px; }\n'
var match_target = null;
if (!targetBranch) {
match_target = 'a#filter-show-all-branches'
} else if (targetBranch == '[default]') {
match_target = 'a#filter-default-branch'
} else {
var branchID = targetBranch.replace('.', '_');
match_target = 'a#filter-branch-' + branchID;
};
return style + match_target + ' { font-weight: bold; }'
};
function installMRFilters() {
var labelFiltersNode = document.querySelectorAll('div.labels-filter')[0];
var WIPNodes = document.querySelectorAll('div.wip-filter');
if (WIPNodes.length == 0) {
var styleSheet = document.createElement('style');
styleSheet.setAttribute('id', 'wip-filter-styles');
styleSheet.innerHTML = getWIPStyles();
document.body.appendChild(styleSheet);
var WIPNode = document.createElement('div');
WIPNode.setAttribute('class', 'filter-item inline wip-filter')
WIPNode.innerHTML = '<i>WIP:</i> <a href="#" id="filter-hide-wip">Hide</a> <a href="#" id="filter-show-wip">Show</a>';
labelFiltersNode.parentNode.insertBefore(WIPNode, labelFiltersNode.nextSibling);
document.getElementById('filter-hide-wip').addEventListener('click', hideWIPMergeRequests, false);
document.getElementById('filter-show-wip').addEventListener('click', showWIPMergeRequests, false);
labelFiltersNode.addEventListener('click', function() { setShowWIP(true); }, false);
}
var BranchNodes = document.querySelectorAll('div.branch-filter');
if (BranchNodes.length == 0) {
styleSheet = document.createElement('style');
styleSheet.setAttribute('id', 'branch-filter-styles');
styleSheet.innerHTML = getBranchStyles();
document.body.appendChild(styleSheet);
var BranchNode = document.createElement('div');
BranchNode.setAttribute('class', 'filter-item inline branch-filter')
var branchHTML = '<i>Branch:</i> <a href="#" id="filter-show-all-branches">All</a> <a href="#" id="filter-default-branch" branch="[default]">Default</a> ';
for (var branchName of targetBranchNames) {
var branchID = branchName.replace('.', '_');
branchHTML = branchHTML + ' <a href="#" id="filter-branch-' + branchID + '" branch="' + branchName + '">' + branchName + '</a>';
}
BranchNode.innerHTML = branchHTML;
labelFiltersNode.parentNode.insertBefore(BranchNode, labelFiltersNode.nextSibling);
document.getElementById('filter-show-all-branches').addEventListener('click', function() { showMergeRequestsByBranch(null); }, false);
document.getElementById('filter-default-branch').addEventListener('click', function() { showMergeRequestsByBranch('[default]'); }, false);
var branchClickHandler = function(event) { showMergeRequestsByBranch(event.target.getAttribute('branch')); }
for (branchName of targetBranchNames) {
branchID = branchName.replace('.', '_');
document.getElementById('filter-branch-'+branchID).addEventListener('click', branchClickHandler, false);
}
}
}
var showWIP = sessionStorage.getItem('gitlab-x-mr-show-wip', 'true') == 'true';
var targetBranch = sessionStorage.getItem('gitlab-x-mr-filter-branch', '') || '';
var targetBranchNames = [];
function populateBranches() {
var branch_targets = document.getElementsByClassName('merge-requests-holder')[0].getElementsByClassName('fa-code-fork');
targetBranchNames = [];
for (var branch_target of branch_targets) {
var branchName = branch_target.nextSibling.textContent.trim();
if (!targetBranchNames.includes(branchName)) {
targetBranchNames.push(branchName);
}
}
targetBranchNames.sort();
console.log("Found branches", targetBranchNames);
}
function initialize() {
populateBranches();
installMRFilters();
if (targetBranch) {
showMergeRequestsByBranch(targetBranch);
} else if (!showWIP) {
hideWIPMergeRequests();
} else {
showWIPMergeRequests();
}
}
waitForKeyElements("div.merge-requests-holder", initialize);
GM_registerMenuCommand('Hide WIP merge requests', hideWIPMergeRequests, 'H');
GM_registerMenuCommand('Show WIP merge requests', showWIPMergeRequests, 'S');
GM_registerMenuCommand('Show merge request from all target branches', function() { return showMergeRequestsByBranch(null) }, '');
GM_registerMenuCommand('Only Show 26.0 merge requests', function() { return showMergeRequestsByBranch("26.0") }, '');
})();
// ==UserScript==
// @name Daily Standup Report from JIRA - Part 1
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Print out the Burnup chart and navigate to print the kanban board
// @author davidf@j5int.com
// @match https://*.atlassian.net/secure/RapidBoard.jspa?*chart=burnupChart*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @grant unsafeWindow
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
function awaitPrintReport() {
console.log("Waiting for report to be ready to print...");
waitForKeyElements("div.ghx-report-issue-list", printReport);
function printReport(jNode) {
console.log("Hiding Burnup Chart issue report list shortly");
window.setTimeout(function() {
console.log("Hiding Burnup Chart issue report list");
jNode.hide();
console.log("Will print shortly...");
window.print();
console.log("Navigating to Kanban board");
window.location.search = window.location.search.replace('&view=reporting', '').replace('&chart=burnupChart', '').replace('&print_burnup_chart=1', '') + '&print_kanban=1';
console.log("Will print on load using another script");
}, 5000);
};
};
GM_registerMenuCommand('Print Daily Standup Report', awaitPrintReport, 'P');
if (window.location.search.indexOf('print_burnup_chart=1') != -1) {
awaitPrintReport();
};
})();
// ==UserScript==
// @name Daily Standup Report from JIRA - Part 2
// @namespace http://tampermonkey.net/
// @version 0.2.1
// @description Print out the kanban board
// @author davidf@j5int.com
// @match https://*.atlassian.net/secure/RapidBoard.jspa?*print_kanban=1*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant unsafeWindow
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
function removeFirstColumn() {
console.log("Hiding left-most column");
var finalColumns = document.querySelectorAll('li.ghx-column:first-of-type');
finalColumns[0].setAttribute('style', 'display: none');
finalColumns[1].setAttribute('style', 'display: none');
};
function removeLastColumn() {
console.log("Hiding right-most column");
var finalColumns = document.querySelectorAll('li.ghx-column:last-of-type');
finalColumns[0].setAttribute('style', 'display: none');
finalColumns[1].setAttribute('style', 'display: none');
};
function hideColumns() {
// for testing phase of sprint
if (window.location.search.indexOf('rapidView=8') != -1) {
removeFirstColumn();
}
removeLastColumn();
}
function awaitPrintKanban() {
console.log("Waiting for load");
waitForKeyElements("div#ghx-pool", printKanban);
function printKanban(jNode) {
console.log("Hiding headers");
document.getElementById('ghx-header').setAttribute('style', 'display:none');
document.getElementById('ghx-operations').setAttribute('style', 'display:none');
window.onbeforeprint = hideColumns;
console.log("Triggering print...");
window.print();
console.log("Done");
};
};
GM_registerMenuCommand('Print Daily Kanban Report', awaitPrintKanban, 'P');
if (window.location.search.indexOf('print_kanban=1') != -1) {
awaitPrintKanban();
};
})();
#!/bin/bash
[ "${1/test/}" != "$1" ] && test_mode=1
echo "Make sure you have installed tampermonkey and the required scripts"
echo "When the page opens, if printing doesn't start automatically, select *Print Daily Standup Report* from the tampermonkey menu"
echo "Make sure you choose Save to PDF, and set the Scale (in extra parameters) to 100%"
echo "Save the first report as 'Daily Burnup.pdf' in this directory"
echo "Save the second report as 'Daily Kanban.pdf' in this directory"
targetView=3
[ "$test_mode" == 1 ] && targetView=8
xdg-open 'https://j5international.atlassian.net/secure/RapidBoard.jspa?rapidView='$targetView'&projectKey=PT&view=reporting&chart=burnupChart&sprint=111&print_burnup_chart=1' >/dev/null 2>/dev/null
read -p "Press any key to generate the standup chart"
date="`date +%Y-%m-%d`"
pdftk "A=Daily Burnup.pdf" "B=Daily Kanban.pdf" cat A B1 output "Daily Standup ${date}.pdf"
xdg-open "Daily Standup ${date}.pdf"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment