Jira ID+Title copy to clipboad feature with various formats
当前为
// ==UserScript== // @name ECOD-JiraHelper-ID-Copier-FullIssue // @namespace http://tampermonkey.net/ // @version 1.7.6 // @description Jira ID+Title copy to clipboad feature with various formats // @author [email protected] // @require https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.6/underscore-umd-min.js // @match https://*jira.fsc.atos-services.net/browse/* // @match https://*jira.fsc.atos-services.net/secure/RapidBoard.jspa* // @match https://*jira.fsc.atos-services.net/projects/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; function goMonkey() { function hookTheMonkey() { var copyIdButton = document.createElement('span'); copyIdButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 30px;' id='copyId' name='copyId' onclick='copyId(this);' title='Copy ID'>ID</span>`; var copyAllButton = document.createElement('span'); copyAllButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 30px;' id='copyAll' name='copyAll' onclick='copyAll(this);' title='Copy ID + Title!'>ID+</span>`; var copyAll4BranchButton = document.createElement('span'); copyAll4BranchButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' id='copyAll4Branch' name='copyAll4Branch' onclick='copyAll(this, "branch");' title='Copy ID + Title (branch)'>Branch</span>`; var copyAll4CommitButton = document.createElement('span'); copyAll4CommitButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' id='copyAll4Commit' name='copyAll4Commit' onclick='copyAll(this, "commit");' title='Copy ID + Title (branch)'>Commit</span>`; var copyAll4MergeButton = document.createElement('span'); copyAll4MergeButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' id='copyAll4Git' name='copyAll4Git' onclick='copyAll(this, "merge");' title='Copy ID + Title (GIT)'>Merge</span>`; var gotoGitLabButton = document.createElement('span'); gotoGitLabButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #5707a6; width: 60px;' name='gotoGitLab' id='gotoGitLab' onclick='goToUrl(this);' title='Go to Gitlab Merge request'>Goto MR</span>`; var shareLinkButton = document.createElement('span'); shareLinkButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; cursor:pointer; background-color: green;' name='shareLink' id='shareLink' onclick='copyAll(this, "share");' title='Sharable link'>Share</span>`; var scriptFunctionCopyId = document.createElement('script'); scriptFunctionCopyId.innerText = `function copyId(el) { let id = document?.querySelector(\"a[id='key-val']\")?.innerHTML?.trim() ?? 'unknown'; if(id === 'unknown'){ id = el?.parentNode?.parentNode?.parentNode?.querySelector(\"[class='ghx-key js-view-in-jira']\")?.innerText?.trim() ?? 'unknown'; } navigator.clipboard.writeText(_.unescape(id)); el.className='monkeyButtons elementToFadeInAndOut'; setTimeout( function(){ el.className='monkeyButtons'; }, 500 ); }`; var scriptFunctionCopyAll = document.createElement('script'); scriptFunctionCopyAll.innerText = `function copyAll(el, option) { let id = document?.querySelector(\"a[id='key-val']\")?.innerHTML?.trim() ?? 'unknown'; if(id === 'unknown'){ id = el?.parentNode?.parentNode?.parentNode?.querySelector(\"[class='ghx-key js-view-in-jira']\")?.innerText?.trim() ?? 'unknown'; } let title = document?.querySelector(\"h1[id='summary-val']\")?.innerHTML?.trim()?.split('<span')[0] ?? 'unknown'; if(title === 'unknown'){ title = el?.parentNode?.parentNode?.parentNode?.querySelector(\"dd[id='summary-val']\")?.innerText?.trim() ?? 'unknown'; } let text4Clipboard = _.unescape(id) + ' ' + _.unescape(title); if(option) { let type = document.querySelector(\"span[id='type-val']\").innerHTML.trim().split('<span')[0].split('">')[1].trim(); let typeBranch = 'feature'; switch (type) { case 'Task': case 'Story': type = 'feat'; typeBranch = 'feature'; break; case 'Bug': type = 'fix'; typeBranch = 'bugfix'; break; default: type = 'feat'; break; }; if(option === 'branch') { text4Clipboard = typeBranch + '/' + _.unescape(id).toLowerCase() + '_' + _.unescape(title).replace(/[^a-zA-Z0-9]+/g, \"_\").toLowerCase().trim(); } if(option === 'commit') { text4Clipboard = type + '(' + _.unescape(id).toLowerCase() + ')' + ': ' + _.unescape(title).replace(/[^a-zA-Z0-9]+/g, \"_\").toLowerCase().trim(); } if(option === 'merge') { text4Clipboard = type + '(' + _.unescape(id).toLowerCase() + ')' + ': ' + _.unescape(title).trim(); } if(option === 'share') { let linkText = _.unescape(id).toUpperCase() + ' ' + _.unescape(title).trim(); let linkUrl = 'https://jira.fsc.atos-services.net/browse/' + _.unescape(id).toUpperCase(); text4Clipboard = '[' + linkText + ']( ' + linkUrl + ' )'; } } navigator.clipboard.writeText(text4Clipboard); el.className='monkeyButtons elementToFadeInAndOut'; setTimeout( function(){ el.className='monkeyButtons'; }, 500 ); } function goToUrl(el){ let baseUrl = 'https://gitlab.ecodesigncloud.com/groups/ecodesign/-/merge_requests?scope=all&state=all&search='; let id = document?.querySelector(\"a[id='key-val']\")?.innerHTML?.trim() ?? 'unknown'; if(id === 'unknown'){ id = el?.parentNode?.parentNode?.parentNode?.querySelector(\"[class='ghx-key js-view-in-jira']\")?.innerText?.trim() ?? 'unknown'; } if(id !== 'unknown'){ window.open(baseUrl + id, '_blank'); } else { el.setStyle('background-color', 'gray'); } } `; var style = document.createElement('style'); style.innerText = ` .jiraButtons { border-radius: 4px; padding: 10px; margin-left:10px; color:white; font-weight:bold; border:0; font-size: 14px; width: 10%; justify-content: center; } .elementToFadeInAndOut { animation: fadeInOut 0.5s linear forwards; } @keyframes fadeInOut { 0% { opacity:0; } 50% { opacity:0.5; } 100% { opacity:1; } } .monkeyButtons { display: inline-flex; border-radius: 5px; padding: 5px; color:white; font-weight:normal; border:0; font-size:14px; width: 50px; justify-content: center; margin-left: 6px }`; document.body.appendChild(scriptFunctionCopyId); document.body.appendChild(scriptFunctionCopyAll); document.body.appendChild(style); let node= document.querySelector('#opsbar-transitions_more') if(node) { let divContainer = document.createElement('div'); divContainer.appendChild(copyIdButton); divContainer.appendChild(copyAllButton); divContainer.appendChild(copyAll4BranchButton); divContainer.appendChild(copyAll4CommitButton); divContainer.appendChild(copyAll4MergeButton); divContainer.appendChild(gotoGitLabButton); divContainer.appendChild(shareLinkButton); divContainer.setAttribute("class", "aui-buttons pluggable-ops"); divContainer.setAttribute("style", "margin-top:10px;"); node.parentNode.appendChild(divContainer); } } function addButtonToNode(node) { if (node) { let copyIdButton = document.createElement('span'); copyIdButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 30px;' name='copyId' id='copyId' onclick='copyId(this);' title='Copy ID only!'>ID</span>`; let copyAllButton = document.createElement('span'); copyAllButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 30px;' name='copyAll' id='copyAll' onclick='copyAll(this);' title='Copy ID + Title!'>ID+</span>`; let copyAll4BranchButton = document.createElement('span'); copyAll4BranchButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' name='copyAll4Branch' id='copyAll4Branch' onclick='copyAll(this, "branch");' title='ID + Title for Branch'>Branch</span>`; let copyAll4CommitButton = document.createElement('span'); copyAll4CommitButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' name='copyAll4Commit' id='copyAll4Commit' onclick='copyAll(this, "commit");' title='ID + Title for Commit'>Commit</span>`; let copyAll4MergeButton = document.createElement('span'); copyAll4MergeButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: purple;' name='copyAll4Merge' id='copyAll4Merge' onclick='copyAll(this, "merge");' title='ID + Title for Merge'>Merge</span>`; let gotoGitLabButton = document.createElement('span'); gotoGitLabButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #5707a6; width: 60px;' name='gotoGitLab' id='gotoGitLab' onclick='goToUrl(this);' title='Go to Gitlab Merge request'>Goto MR</span>`; let shareLinkButton = document.createElement('span'); shareLinkButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: green;' name='shareLink' id='shareLink' onclick='copyAll(this, "share");' title='Sharable link'>Share</span>`; let divContainer = document.createElement('div'); divContainer.appendChild(copyIdButton); divContainer.appendChild(copyAllButton); if(node.id !== 'ghx-detail-issue'){ divContainer.appendChild(copyAll4BranchButton); divContainer.appendChild(copyAll4CommitButton); divContainer.appendChild(copyAll4MergeButton); } divContainer.appendChild(gotoGitLabButton); divContainer.appendChild(shareLinkButton); divContainer.setAttribute("class", "aui-buttons pluggable-ops"); //backlog if(node.id === 'ghx-detail-issue'){ divContainer.setAttribute("style", "margin-top: 10px; margin-left: 45px;"); node.insertBefore(divContainer, node.firstChild); } //issues if(node.id === 'stalker'){ divContainer.setAttribute("style", "margin-bottom:10px; margin-left: 14px;"); node.appendChild(divContainer); } //dedicated issue page if(node.id === 'opsbar-transitions_more') { divContainer.setAttribute("style", "margin-top:10px;"); node.parentNode.appendChild(divContainer); } } } // Callback function to observe mutations in the DOM function handleMutations(mutationsList, observer) { for (var mutation of mutationsList) { // Check if nodes were added to the DOM //console.debug('mutation.type', mutation.type) if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { // Loop through the added nodes and check if any of them contain the modal content mutation.addedNodes.forEach(function(node) { //console.debug("NODE: " + node.id); if (node.id === 'opsbar-transitions_more' || node.id === 'stalker' || node.id === 'ghx-detail-issue') { // Replace with the actual ID of the modal container // Call the function to add the button to the modal //console.debug("FOUND: " + node.id); addButtonToNode(node); } }); } } } // Create a new MutationObserver var observer = new MutationObserver(handleMutations); hookTheMonkey(); // Start observing the body for DOM changes observer.observe(document.body, { childList: true, subtree: true }); } goMonkey(); })();