您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Copy JIRA issues from sprints in one big list
当前为
// ==UserScript== // @name ECOD-Jira-List-Copier // @namespace ecod.jira.list-copy // @version 1.1.1 // @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 }); })();