// ==UserScript== // @name AsanaAdditions // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author mtib.becker@gmail.com // @match https://app.asana.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=asana.com // @grant none // ==/UserScript== (function() { 'use strict'; /** * @param {object} options * @param {string} options.key * @param {({ title, taskId }: { title: string; taskId: string; }) => { label: string; value: string; onClick?: () => void; }} options.toRow */ const updateAsanaRow = (options) => { const { key } = options; const taskRegex = /^\/\d+(\/\S+)?\/(\d+|inbox)\/(\d+)/ const taskMatch = taskRegex.exec(window.location.pathname); if (!taskMatch) { return; } const taskId = taskMatch[3]; const tableElement = document.querySelector('.TaskPaneFields'); const titleElement = document.querySelector('div.ObjectTitleInput.TaskPane-titleRow.TaskPane-titleRowInput > div > textarea'); if (!tableElement) { throw new Error('Cannot find required DOM elements: tableElement'); } if (!titleElement) { throw new Error('Cannot find required DOM elements: titleElement'); } const title = titleElement.innerHTML; const { label, value, onClick } = options.toRow({ title, taskId }); const rootElementId = `boost-watched-${key}`; const existingRoot = document.getElementById(rootElementId); if (existingRoot && existingRoot.dataset.label === label && existingRoot.dataset.value === value) { return; } else if (existingRoot && existingRoot.parentElement) { existingRoot.parentElement.removeChild(existingRoot); } const addedRowElement = document.createElement('div'); addedRowElement.id = rootElementId; addedRowElement.dataset.value = value; addedRowElement.dataset.label = label; addedRowElement.classList.add('LabeledRowStructure'); const labelDiv1 = document.createElement('div'); labelDiv1.classList.add('LabeledRowStructure-left'); labelDiv1.style.width = '120px'; addedRowElement.appendChild(labelDiv1); const labelDiv2 = document.createElement('div'); labelDiv2.classList.add('LabeledRowStructure-labelContainer'); labelDiv1.appendChild(labelDiv2); const labelLabel = document.createElement('label'); labelLabel.classList.add('LabeledRowStructure-label'); labelLabel.innerHTML = label; labelDiv2.appendChild(labelLabel); const valueDiv1 = document.createElement('div'); valueDiv1.classList.add('LabeledRowStructure-right'); addedRowElement.appendChild(valueDiv1); const valueDiv2 = document.createElement('div'); valueDiv2.classList.add('LabeledRowStructure-content'); valueDiv2.style.display = 'flex'; valueDiv2.style.gap = '10px'; valueDiv1.appendChild(valueDiv2); const follower = document.createElement('span'); follower.style.color = '#272'; const clickableBranchNameElement = document.createElement('span'); clickableBranchNameElement.style.minWidth = '0px'; clickableBranchNameElement.style.flexShrink = '1'; clickableBranchNameElement.style.textOverflow = 'ellipsis'; clickableBranchNameElement.style.whiteSpace = 'nowrap'; clickableBranchNameElement.style.overflow = 'hidden'; clickableBranchNameElement.innerHTML = value; if (onClick) { clickableBranchNameElement.style.cursor = 'pointer'; clickableBranchNameElement.onclick = () => { onClick(); follower.innerHTML = 'clicked!'; } } valueDiv2.appendChild(clickableBranchNameElement); valueDiv2.appendChild(follower); tableElement.insertBefore(addedRowElement, tableElement.childNodes[tableElement.childNodes.length -1]); } const updateBranchName = () => { updateAsanaRow({ key: 'boost-branch-id', toRow: ({ title, taskId }) => { const branchName = [...(title.toLocaleLowerCase().replace(/[^a-z0-9 ]/ig, '').split(' ').slice(0, 8)), taskId].join('-'); return { label: 'Canonical branch', value: branchName, onClick: () => { navigator.clipboard.writeText(branchName); } } } }) } const updateCatsay = () => { updateAsanaRow({ key: 'cat', toRow: ({title}) => { const url = new URL(`https://cataas.com/cat/says/${encodeURIComponent(title)}`); const imgElement = document.createElement('img'); imgElement.src = url.href; imgElement.style.width = '100%'; console.log(imgElement.outerHTML); return { label: 'Cat', value: imgElement.outerHTML }; }}); } window.setInterval(() => { updateBranchName(); updateAsanaRow({ key: 'numberwang', toRow: () => ({ label: 'Numberwang', value: Math.random() })}); updateCatsay(); }, 1000); })();