您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Jira ID + Title copy to clipboad feature with various formats. (Note: Jira View Workflow does not work with this extension)
当前为
// ==UserScript== // @name ECOD-JiraHelper-Copier // @namespace ecod.jira.copier // @version 1.8.2 // @description Jira ID + Title copy to clipboad feature with various formats. (Note: Jira View Workflow does not work with this extension) // @author CRK // @require https://cdn.jsdelivr.net/npm/[email protected]/lodash.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 hookTheJiraMonkey() { var copyIdButton = document.createElement('span'); copyIdButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 20px;' id='copyId' name='copyId' onclick='copyToClipboard(this, "id");' title='Copy ID'>ID</span>`; var copyToClipboardButton = document.createElement('span'); copyToClipboardButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 25px;' id='copyToClipboard' name='copyToClipboard' onclick='copyToClipboard(this);' title='Copy ID + Title!'>ID+</span>`; var copyToClipboard4BranchButton = document.createElement('span'); copyToClipboard4BranchButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' id='copyToClipboard4Branch' name='copyToClipboard4Branch' onclick='copyToClipboard(this, "branch");' title='Copy ID + Title (branch)'>Branch</span>`; var copyToClipboard4CommitButton = document.createElement('span'); copyToClipboard4CommitButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' id='copyToClipboard4Commit' name='copyToClipboard4Commit' onclick='copyToClipboard(this, "commit");' title='Copy ID + Title (branch)'>Commit</span>`; var copyToClipboard4MergeButton = document.createElement('span'); copyToClipboard4MergeButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' id='copyToClipboard4Git' name='copyToClipboard4Git' onclick='copyToClipboard(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; width: 30px; padding: 7px;' name='shareLink' id='shareLink' onclick='copyToClipboard(this, "share");' title='Sharable link'><span class="icon aui-icon aui-icon-small aui-iconfont-share"></span></span>`; var scriptFunctioncopyToClipboard = document.createElement('script'); scriptFunctioncopyToClipboard.innerText = ` function copyToClipboard(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'; } id = _.deburr(_.unescape(id.trim())); let text4Clipboard = id; if(option !== 'id') { 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'; } title = _.deburr(_.unescape(title.trim())); text4Clipboard += ' ' + title; if(['branch', 'commit', 'merge'].includes(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 + '/' + id.toLowerCase() + '_' + title.replace(/[^a-zA-Z0-9]+/g, \"_\").toLowerCase().replace(/_+$/, ''); } if(option === 'commit') { text4Clipboard = type + '(' + id.toLowerCase() + ')' + ': ' + title.replace(/[^a-zA-Z0-9]+/g, \"_\").toLowerCase().replace(/_+$/, ''); } if(option === 'merge') { text4Clipboard = type + '(' + id.toLowerCase() + ')' + ': ' + title; } } if(option === 'share') { let linkText = id.toUpperCase() + ' ' + title.trim(); let linkUrl = 'https://jira.fsc.atos-services.net/browse/' + 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(scriptFunctioncopyToClipboard); document.body.appendChild(style); let node = document.querySelector('#opsbar-transitions_more') if(node) { let divContainer = document.createElement('div'); divContainer.appendChild(copyIdButton); divContainer.appendChild(copyToClipboardButton); divContainer.appendChild(copyToClipboard4BranchButton); divContainer.appendChild(copyToClipboard4CommitButton); divContainer.appendChild(copyToClipboard4MergeButton); divContainer.appendChild(gotoGitLabButton); divContainer.appendChild(shareLinkButton); divContainer.setAttribute("class", "aui-buttons pluggable-ops"); divContainer.setAttribute("style", "margin-top:10px;"); node.parentNode.appendChild(divContainer); } } function injectButtonsToNode(node) { if (node) { let copyIdButton = document.createElement('span'); copyIdButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 20px;' name='copyId' id='copyId' onclick='copyToClipboard(this, "id");' title='Copy ID only!'>ID</span>`; let copyToClipboardButton = document.createElement('span'); copyToClipboardButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: #0747a6; width: 25px;' name='copyToClipboard' id='copyToClipboard' onclick='copyToClipboard(this);' title='Copy ID + Title!'>ID+</span>`; let copyToClipboard4BranchButton = document.createElement('span'); copyToClipboard4BranchButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' name='copyToClipboard4Branch' id='copyToClipboard4Branch' onclick='copyToClipboard(this, "branch");' title='ID + Title for Branch'>Branch</span>`; let copyToClipboard4CommitButton = document.createElement('span'); copyToClipboard4CommitButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' name='copyToClipboard4Commit' id='copyToClipboard4Commit' onclick='copyToClipboard(this, "commit");' title='ID + Title for Commit'>Commit</span>`; let copyToClipboard4MergeButton = document.createElement('span'); copyToClipboard4MergeButton.innerHTML = `<span class='monkeyButtons' style='cursor:pointer; background-color: blue;' name='copyToClipboard4Merge' id='copyToClipboard4Merge' onclick='copyToClipboard(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; width: 30px; padding: 7px;' name='shareLink' id='shareLink' onclick='copyToClipboard(this, "share");' title='Sharable link'><span class="icon aui-icon aui-icon-small aui-iconfont-share"></span></span>`; let divContainer = document.createElement('div'); divContainer.appendChild(copyIdButton); divContainer.appendChild(copyToClipboardButton); if(node.id !== 'ghx-detail-issue'){ divContainer.appendChild(copyToClipboard4BranchButton); divContainer.appendChild(copyToClipboard4CommitButton); divContainer.appendChild(copyToClipboard4MergeButton); } divContainer.appendChild(gotoGitLabButton); divContainer.appendChild(shareLinkButton); divContainer.setAttribute("class", "aui-buttons pluggable-ops"); //backlog if(node.id === 'ghx-detail-issue' && node.firstChild){ 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 (browse) 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 handleDomMutations(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 && (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); injectButtonsToNode(node); } }); } } } hookTheJiraMonkey(); // Create a new MutationObserver var domObserver = new MutationObserver(handleDomMutations); // Start observing the body for DOM changes domObserver.observe(document.body, { childList: true, subtree: true }); })();