Skip to content

Instantly share code, notes, and snippets.

@tk3
Last active November 9, 2021 06:41
Show Gist options
  • Save tk3/99fd9ac67860c10e1b75240dbd1367a4 to your computer and use it in GitHub Desktop.
Save tk3/99fd9ac67860c10e1b75240dbd1367a4 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Download Backlog Kanban
// @namespace http://tampermonkey.net/
// @version 0.1
// @description You can save the state of the issue displayed in Backlog Kanban. The method is download and copy to clipboard.
// @author tk3
// @match https://*.backlog.jp/board/*
// @match https://*.backlog.com/board/*
// @grant GM_setClipboard
// ==/UserScript==
const debug = false;
function debugLog(message) {
if (!debug) return;
console.log(message);
}
function create_clipboard_link(elem) {
const a = document.createElement('a');
const linkText = document.createTextNode("[ to clipboard ]");
a.appendChild(linkText);
a.title = "to clipboard";
a.href = "#";
elem.appendChild(a);
return a;
}
function create_download_link(elem) {
const a = document.createElement('a');
const linkText = document.createTextNode("[ download ]");
a.appendChild(linkText);
a.title = "download";
a.href = "#";
elem.appendChild(a);
return a;
}
function get_data_in_kanban() {
const data = [];
const statusElemList = document.querySelectorAll('#kanban > div > div > div:nth-child(3) > div > section');
const statusElemListLength = statusElemList.length;
for (var i = 0; i < statusElemListLength; i++) {
debugLog(i);
const statusElem = statusElemList[i];
const statusName = statusElem.querySelector('div > h3 > div:nth-child(2)').innerText;
debugLog('status name: ' + statusName);
const issuesElemList = statusElem.querySelectorAll('ul > li');
const issuesElemListLength = issuesElemList.length;
for (var j = 0; j < issuesElemListLength; j++ ) {
const issue = issuesElemList[j];
// issueType
const issueType = issue.querySelector('li > div:nth-child(1) span').innerText;
// issueKey
const issueKey = issue.querySelector('li > div:nth-child(1) a').text;
// issue link
const issueLink = issue.querySelector('li > div:nth-child(1) a').href;
// summary
const summary = issue.querySelector('li > p').innerText;
debugLog('issue type: '+ issueType);
debugLog('issue key: ' + issueKey);
debugLog('issue link: ' + issueLink);
debugLog('summary: ' + summary);
const record = {
'status': statusName,
'issueSummary': summary,
'issueKey': issueKey,
'issueType': issueType,
'issueLink': issueLink
};
data.push(record);
}
}
return data;
}
function to_tsv(data) {
const length = data.length;
var text = get_header(data);
for (var i = 0; i < length; i++) {
const record = data[i];
const s = record.status + '\t' +
record.issueSummary + '\t' +
record.issueKey + '\t' +
record.issueType + '\t' +
record.issueLink;
text += s + '\n';
}
return text;
}
function get_header(data) {
if (data.length) return '';
const r = data[0];
const keys = Object.keys(data[0]);
return keys.join('\t') + '\n';
}
(function() {
'use strict';
const elem = document.querySelector('#project-header > div > div');
const clipboard_link = create_clipboard_link(elem);
function copy_to_clipboard(event) {
debugLog('copy_to_clipboard() ----');
const data = get_data_in_kanban();
GM_setClipboard(to_tsv(data));
event.preventDefault();
}
clipboard_link.addEventListener("click", copy_to_clipboard);
const download_link = create_download_link(elem);
function download_kanban_data(event) {
debugLog('download_kanban_data() ----');
const data = get_data_in_kanban();
const blob = new Blob([(to_tsv(data))], {type : 'text/csv'});
const url = URL.createObjectURL(blob);
download_link.download = 'kanban.csv';
download_link.href = url;
}
download_link.addEventListener("click", download_kanban_data);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment