Skip to content

Instantly share code, notes, and snippets.

@yheihei
Last active January 12, 2022 06:17
Show Gist options
  • Save yheihei/1472e146615b6ff2d622f079765c538c to your computer and use it in GitHub Desktop.
Save yheihei/1472e146615b6ff2d622f079765c538c to your computer and use it in GitHub Desktop.
JIRAのカンバンボードにコピーボタンを追加するユーザースクリプト
// ==UserScript==
// @name カンバンでのコピーボタン挿入
// @namespace https://yhei-web-design.com
// @version 0.1
// @description JIRAのカンバンにチケットのタイトルコピーボタンを追加する
// @author yhei.register@gmail.com
// @match https://*.atlassian.net/jira/software/projects/XMAR/boards/*
// @icon https://www.google.com/s2/favicons?domain=atlassian.net
// @grant none
// ==/UserScript==
(function() {
'use strict';
// ボタンのテンプレート定義
const buttonTemplate = {
name: 'copyButton',
tag: 'div',
label: 'コピー',
className: 'aui-button aui-button-primary js-title-copy-button puw1ku-0 fhIWEf',
css: `
width: auto;
font-size: 10px;
position:absolute;
right: 0;
bottom: 0
`
}
/**
* 指定のタグ、クラス、CSS、ラベルでボタンのNodeを作成する
*
* @param {object} buttonTemplate
* @return {Node}
*/
function createCopyButtonElement(buttonTemplate) {
const buttonNode = document.createElement(buttonTemplate.tag);
buttonNode.dataset.name = buttonTemplate.name;
buttonNode.className = buttonTemplate.className;
buttonNode.style.cssText = buttonTemplate.css;
buttonNode.innerHTML = buttonTemplate.label;
return buttonNode;
}
function addCopyButtonToContainer(issueLinkContainer) {
const cards = issueLinkContainer.querySelectorAll('div[id^="card-XMAR-"]')
cards.forEach((element) => {
const title = element.querySelector('span').textContent
// console.log(title)
const ticketNumber = element.querySelector('div[role="presentation"] span').textContent
// console.log(ticketNumber)
const copyTitle = `${ticketNumber}_${title}`
// console.log(copyTitle)
// 課題毎にボタンを作成する
const buttonNode = createCopyButtonElement(buttonTemplate);
// ボタンにコピーボタンが押された時の処理を追加
buttonNode.onclick = function(event) {
// 親要素へのバブリングを停止する
event.stopPropagation();
// コピーする文字列を作成
const copiedString = `${ticketNumber}_${title}`;
// コピー用のDOMを作り 選択状態にする
const domForClipboard = document.createElement('div');
domForClipboard.appendChild(document.createElement('pre')).textContent = copiedString;
domForClipboard.style.cssText = `
position: fixed;
left: -100%;
`;
document.body.appendChild(domForClipboard);
document.getSelection().selectAllChildren(domForClipboard);
// 選択したコピー用のDOMをコピーする
const result = document.execCommand('copy');
// コピー用のDOMを削除
document.body.removeChild(domForClipboard);
return result;
};
element.querySelector('.puw1ku-1').appendChild(buttonNode);
})
}
/**
* 初期化関数
*
* @return {void}
*/
function initialize() {
// const observer = new MutationObserver(function(mutations) {
// 課題一覧のコンテナを取得する
const issueLinkContainer = document.querySelector('[data-test-id="software-board.board"]');
if (!issueLinkContainer) {
return;
}
addCopyButtonToContainer(issueLinkContainer);
// });
// DOMの変更を検知したら ロード
// observer.observe(document, { childList: true, subtree: true });
}
// 5s後、ボタン追加
setTimeout(initialize, 5000);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment