mチケット詳細にて、チケット情報(チケットID・題名・URL)をワンクリックでコピーできるボタンを追加する(View Customizeスクリプト)
チケットの情報をメールやチャット等の他ツールに転記する際、
ブラウザとツールを行き来することに手間を感じるため、1クリックでコピーできるボタンを追加する機能をView Customizeで作成しました。
使い方¶
スクリプトを適用すると、チケット名の左にボタンが表示されます。
ボタンをクリックすると、「チケットID」「チケット題名」「URL」がクリップボードにコピーされます。
貼り付けると、以下の形式になります。
View Customizeの設定¶
パスのパターン:/issues
プロジェクトのパターン:
挿入位置:全ページの末尾
種別:JavaScript
// コピーボタンのスタイルを追加
const style = document.createElement('style');
style.innerHTML = `
.vc_copyIssueInfo {
position: relative;
cursor: pointer;
display: inline-block;
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
width: 24px;
height: 24px;
background-position: center;
background-repeat: no-repeat;
background-size: 14px 14px;
vertical-align: middle;
background-color: #fff;
border: 1px solid #bbb;
font-size: 12px;
line-height: 16px;
margin-right: 4px;
margin-top: -4px;
padding: 0;
border-radius: 6px;
transition: background-image 0.2s;
box-shadow: 0px 4px 6px -1px rgba(0, 0, 0, 0.10), 0px 2px 4px -2px rgba(0, 0, 0, 0.10);
}
.vc_copyIssueInfo:hover {
background-color: #f0f2f3;
}
.vc_copyIssueInfo:active {
background-color: #dde9ee;
}
`;
document.head.appendChild(style);
// チケットタイトルの取得
function getCleanTitle(selector) {
const el = document.querySelector(selector);
if (!el) return '';
const excludedElement = el.querySelector('button');
let text = '';
el.childNodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE) {
text += node.textContent;
} else if (node.nodeType === Node.ELEMENT_NODE && node !== excludedElement) {
text += node.textContent;
}
});
return text;
}
// チケット情報のコピー
function quickCopy() {
const requiredClasses = ['controller-issues', 'action-show']
if(!requiredClasses.every(el => document.body.classList.contains(el))) return
const copyBtn = document.createElement('button')
copyBtn.textContent = 'チケット情報をコピー'
copyBtn.title = 'チケット情報をコピー'
copyBtn.className = 'vc_copyIssueInfo'
copyBtn.classList.add('icon')
copyBtn.classList.add('icon-copy')
const issueIdAndTracker = document.querySelector('#content .issue .subject h3')
if(issueIdAndTracker) {
issueIdAndTracker.prepend(copyBtn)
}
copyBtn.addEventListener('click', (e) => {
// urlの取得
const url = encodeURI(window.location.href);
// チケットIDの生成
const pathSegments = new URL(url).pathname.split('/')
const issueId = pathSegments[pathSegments.length - 1]
// チケット題名の取得
const issueSubject = getCleanTitle('#content .issue .subject h3')
// [チケットID+題名 \n URL]の形を作る
const issueInfo = `#${issueId} ${issueSubject}\n${url}`
if(issueInfo) {
navigator.clipboard.writeText(issueInfo).then(() => {
copyBtn.classList.add('icon-checked')
setTimeout(() => {
copyBtn.classList.remove('icon-checked')
}, 1250)
}).catch(error => {
console.log('チケットIDのコピーに失敗しました', error)
})
} else {
console.log('チケットIDが取得できません')
}
})
}
window.addEventListener('DOMContentLoaded', () => {
quickCopy()
})
注意¶
- これらのスクリプトに関して、作者は作者としての権利を一切行使しません。
- 商用利用ももちろんOKです。改変も自由です。再配布についても出所を示す必要はありません。
- これらのスクリプトを利用した場合、いかなる支障が起きたとしてもその責任を負いません。ご利用は自己責任でお願いします。
- また、不具合が発見された場合の改修やRedmineやLychee Redmineのバージョンアップに際してのメンテナンスの義務も負いません。
- 上記についてご了承いただける方のみ、ご利用ください。
いいね!0