Copy JIRA issues from sprints in one big list
当前为
// ==UserScript==
// @name ECOD-Jira-List-Copier
// @namespace jira.list-copy
// @version 1.1.0
// @description Copy JIRA issues from sprints in one big list
// @author CRK
// @require https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-umd-min.js
// @match https://jira.fsc.atos-services.net/secure/RapidBoard.jspa?rapidView*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
function hookTheMonkeyForJira() {
var scriptFunctionCopyList = document.createElement('script');
scriptFunctionCopyList.innerText = `function copyList(node, $case) {
let tiles = node.parentNode.parentNode.parentNode.parentNode.nextElementSibling.querySelectorAll("div[data-issue-key]");
let listData = [];
tiles.forEach(function (tile) {
if(tile.attributes && tile.attributes){
let id = tile.attributes['data-issue-key'].value;
let issue = '?';
let type = '?';
let status = '?';
let priority = '?';
let link = '?';
if(tile.childNodes[0] && tile.childNodes[0].attributes && tile.childNodes[0].attributes['aria-label']){
issue = tile.childNodes[0].attributes['aria-label'].value;
}
if(tile.childNodes[1] && tile.childNodes[1].childNodes[0] && tile.childNodes[1].childNodes[0].childNodes[0] && tile.childNodes[1].childNodes[0].childNodes[0].attributes['title']){
type = tile.childNodes[1].childNodes[0].childNodes[0].attributes['title'].value;
}
if(tile.childNodes[1] && tile.childNodes[1].childNodes[0] && tile.childNodes[1].childNodes[0].childNodes[1] && tile.childNodes[1].childNodes[0].childNodes[1].childNodes[0].attributes['title']){
priority = tile.childNodes[1].childNodes[0].childNodes[1].childNodes[0].attributes['title'].value;
}
if(tile.childNodes[1] && tile.childNodes[1].childNodes[0] && tile.childNodes[1].childNodes[0].childNodes[2] && tile.childNodes[1].childNodes[0].childNodes[2].childNodes[0].attributes['href']){
link = 'https://jira.fsc.atos-services.net' + tile.childNodes[1].childNodes[0].childNodes[2].childNodes[0].attributes['href'].value;
}
if(tile.childNodes[1] && tile.childNodes[1].childNodes[1] && tile.childNodes[1].childNodes[1].childNodes[0] && tile.childNodes[1].childNodes[1].childNodes[0].childNodes[0]){
status = tile.childNodes[1].childNodes[1].childNodes[0].childNodes[0].innerText;
}
listData.push({'id': id, 'issue': issue, 'type': type, 'status': status, 'priority': priority, 'link': link});
}
});
listData.sort((a, b) => {
if (a.type < b.type) return -1;
if (a.type > b.type) return 1;
if (a.priority < b.priority) return -1;
if (a.priority > b.priority) return 1;
return 0;
});
clip = '';
switch($case){
case 'simple':
listData.forEach((row) => clip += ' - ' + row.issue + '\\r\\n');
break;
case 'lines':
listData.forEach((row) => clip += '[' + row.type + '] [' + row.priority + '] ' + row.issue + '\\r\\n');
break;
case 'csv':
listData.forEach((row) => clip += row.type + ';' + row.priority + ';' + row.issue + ';' + row.status + ';' + row.link + '\\r\\n');
break;
default:
listData.forEach((row) => clip += '[' + row.type + '][' + row.priority + ']' + row.issue + '\\r\\n');
};
navigator.clipboard.writeText(_.unescape(clip));
node.className='monkeyButtons elementToFadeInAndOut';
setTimeout(
function(){
node.className='monkeyButtons';
}, 500
);
}`;
var style = document.createElement('style');
style.innerText = `
.elementToFadeInAndOut {
animation: fadeInOut 0.5s linear forwards;
}
@keyframes fadeInOut {
0% { opacity:0; }
50% { opacity:0.5; }
100% { opacity:1; }
}
.monkeyButtons {
cursor:pointer;
background-color: #371cf2;;
width: auto;
border-radius: 5px;
color: white;
font-size: 12px;
font-weight: bold;
padding-top: 2px;
padding-bottom: 2px;
}`;
document.body.appendChild(scriptFunctionCopyList);
document.body.appendChild(style);
}
function addButtonToNode(node) {
var copyButton0 = document.createElement('span');
copyButton0.setAttribute("style" ,"cursor:pointer; display: inline; padding-left: 0px; padding-right: 10px;");
copyButton0.classList.add('ghx-sprint-info');
copyButton0.innerHTML = `<span
class='monkeyButtons'
name='copyList'
id='copyList'
onclick='copyList(this, "simple");'
title='Copy list as simple list'>Copy as Simple-list</span>`;
var copyButton1 = document.createElement('span');
copyButton1.setAttribute("style" ,"cursor:pointer; display: inline; padding-left: 0px; padding-right: 10px;");
copyButton1.classList.add('ghx-sprint-info');
copyButton1.innerHTML = `<span
class='monkeyButtons'
name='copyList'
id='copyList'
onclick='copyList(this, "lines");'
title='Copy list as Detailed List'>Copy as Detailed-list</span>`;
var copyButton2 = document.createElement('span');
copyButton2.setAttribute("style" ,"cursor:pointer; display: inline; padding-left: 0px; margin-right:40px;");
copyButton2.classList.add('ghx-sprint-info');
copyButton2.innerHTML = `<span
class='monkeyButtons'
name='copyList'
id='copyList'
onclick='copyList(this, "csv");'
title='Copy list as CSV'>Copy as CSV-export</span>`;
if(node && node.firstChild && node.firstChild.getElementsByClassName('ghx-sprint-info')) {
let divContainer = document.createElement('div');
divContainer.appendChild(copyButton0);
divContainer.appendChild(copyButton1);
divContainer.appendChild(copyButton2);
divContainer.setAttribute("style", "margin-left: auto;");
node.firstChild.getElementsByClassName('ghx-sprint-info')[0].appendChild(divContainer);
}
}
// Callback function to observe mutations in the DOM
function handleJiraMutations(mutationsList, observer) {
for (var mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(function(node) {
//console.debug("NODE: ", node.attributes && node.attributes['data-sprint-id']);
if (node.attributes && node.attributes['data-sprint-id']) {
//console.debug("FOUND: " + node.id);
addButtonToNode(node);
}
});
}
}
}
hookTheMonkeyForJira();
// Create a new MutationObserver
var boardObserver = new MutationObserver(handleJiraMutations);
// Start observing the body for DOM changes
boardObserver.observe(document.body, {
childList: true,
subtree: true
});
})();