Show advanced statuses
// ==UserScript==
// @name BitBucket Advanced Statuses
// @version 1.0
// @description Show advanced statuses
// @icon https://clipground.com/images/png-connection-status.png
// @author Mihai Stancu
// @license MIT
// @namespace msus
// @match https://bitbucket.org/*/*/pull-requests*
// @grant GM_addStyle
// @run-at document-idle
// ==/UserScript==
(() => new MutationObserver(main).observe(document.querySelector('body'), {childList: true, subtree: true}))();
function main(mutations, observer) {
const PRs = document.querySelectorAll('[data-qa=pull-request-row]');
if (!PRs[0]) {
return;
}
observer.disconnect();
const table = PRs[0].closest('table');
table.insertAdjacentHTML('beforeend', '<tbody class="pseudo-header"><tr><th colspan=15>Approved</th></tr></tbody>');
table.insertAdjacentHTML('beforeend', '<tbody class="approved"></tbody>');
table.insertAdjacentHTML('beforeend', '<tbody class="pseudo-header"><tr><th colspan=15>Needs review</th></tr></tbody>');
table.insertAdjacentHTML('beforeend', '<tbody class="needs-review"></tbody>');
table.insertAdjacentHTML('beforeend', '<tbody class="pseudo-header"><tr><th colspan=15>In progress</th></tr></tbody>');
table.insertAdjacentHTML('beforeend', '<tbody class="in-progress"></tbody>');
for (const PR of PRs) {
table.querySelector('tbody.' + status(PR)).appendChild(PR);
}
}
/**
* @param {Element} item
*
* @returns {string}
*/
function status(item) {
/** If changes have been requested => in progress */
const rejection = item.querySelector('[aria-label="avatar group"] [alt*=" requested changes "]');
if (rejection) {
return 'in-progress';
}
/** If there are open tasks => in progress */
const activities = item.querySelectorAll('td:nth-child(2)')
for (const activity of activities) {
if (activity.innerHTML.includes(' open tasks')) {
return 'in-progress';
}
}
/** If there are open tasks => in progress */
const avatars = item.querySelectorAll('[aria-label="avatar group"] img[alt]');
const approvals = item.querySelectorAll('[aria-label="avatar group"] img[alt*=" approved "]');
if (approvals.length >= 1 && avatars.length === approvals.length) {
return 'approved';
}
if (approvals.length >= 2) {
return 'approved';
}
return 'needs-review';
}
GM_addStyle(`
.pseudo-header {
border-bottom: 0px;
}
.pseudo-header th {
padding-top: 32px;
}
tbody.needs-review {
border-bottom: 0;
border-top: 2px solid #FFAB00;
}
tbody.approved {
border-bottom: 0;
border-top: 2px solid #00875A;
}
tbody.in-progress {
border-bottom: 0;
border-top: 2px solid #DE350B;
}
`);