Skip to content

Instantly share code, notes, and snippets.

@felixfbecker
Created September 16, 2021 15:50
Show Gist options
  • Save felixfbecker/c87090d052c3813d7e90b500e5aed562 to your computer and use it in GitHub Desktop.
Save felixfbecker/c87090d052c3813d7e90b500e5aed562 to your computer and use it in GitHub Desktop.
Tampermonkey script to sum up estimates in GitHub Beta project boards
// ==UserScript==
// @name GitHub estimate sum
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://github.com/orgs/sourcegraph/projects/*
// @icon https://www.google.com/s2/favicons?domain=github.com
// @grant none
// ==/UserScript==
(async function() {
'use strict';
await new Promise(resolve => setTimeout(resolve, 1000))
const estimateHeader = [...document.querySelectorAll('[role="columnheader"]')].find(el => /estimate/i.test(el.textContent))
if (!estimateHeader) {
return
}
const estimateColumnIndex = [...estimateHeader.parentElement.children].indexOf(estimateHeader)
const assigneeHeader = [...document.querySelectorAll('[role="columnheader"]')].find(el => /assignee/i.test(el.textContent))
const assigneeColumnIndex = [...assigneeHeader.parentElement.children].indexOf(assigneeHeader)
function getSum(group) {
const cells = [...group.querySelectorAll(`[role="cell"]:nth-child(${estimateColumnIndex + 1})`)]
const estimatesByAssignee = { all: 0 }
for (const cell of cells) {
const estimate = parseFloat(cell.textContent) || 0
const row = cell.closest('[role="row"]')
const assigneeCell = row.querySelector(`[role="cell"]:nth-child(${assigneeColumnIndex + 1})`)
const assignees = [...assigneeCell.querySelectorAll('img[src^="https://avatars.githubusercontent.com/"]')].map(img => img.alt)
for (const assignee of assignees) {
estimatesByAssignee[assignee] = estimatesByAssignee[assignee] ?? 0
estimatesByAssignee[assignee] += estimate
estimatesByAssignee.all += estimate
}
}
return estimatesByAssignee
}
const groups = document.querySelectorAll('[data-test-id^="table-group-"] > .Box-nv15kw-0.dHXePK')
for (const group of groups) {
const estimatesByAssignee = getSum(group)
for (const [assignee, sum] of Object.entries(estimatesByAssignee)) {
const badge = makeSumBadge(sum, 'CounterLabel-sc-1ubx52d-0 gLeezM')
badge.style.marginLeft = '0.25rem'
badge.style.marginRight = '0.5rem'
group.querySelector('[data-test-id="table-group-name"]').parentNode.append(...(assignee === 'all' ? [] : [makeAvatar(assignee), ` ${assignee}: `]), badge)
}
}
function makeAvatar(username) {
return document.querySelector(`img[alt="${username}"]`).cloneNode()
}
function makeSumBadge(sum, className) {
const span = document.createElement('span')
span.className = className
span.textContent = sum + 'd'
return span
}
estimateHeader.childNodes[0].childNodes[0].append(' ', makeSumBadge(getSum(document).all, 'Label-sc-1t3ykp0-0 eHlHiL'))
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment