Last active
August 28, 2025 11:57
-
-
Save millerdev/571f894f7b71b55168fab694d636f125 to your computer and use it in GitHub Desktop.
Greasemonkey script to hide requested PTO from the Clockify time tracker view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Clockify - hide PTO | |
| // @description Hides PTO cards in Clockify time tracker. Requested/future PTO takes up a lot of space at the top of the time tracker, which pushes today's time entries down in the list. This script hides PTO entries by default, and adds a button to toggle their visibility. | |
| // @version 1.5 | |
| // @include https://dimagi.clockify.me/tracker* | |
| // @grant none | |
| // ==/UserScript== | |
| // | |
| // Mostly written by ChatGPT with minor modifications. | |
| // Source: https://gist.github.com/millerdev/571f894f7b71b55168fab694d636f125 | |
| (() => { | |
| const PTO_DESCRIPTION = "PTO - Annual Leave"; | |
| const ptoCards = []; | |
| let shouldHide = true; | |
| function main() { | |
| if (shouldHide && hidePTOCards()) { | |
| addPTOToggle(); | |
| } | |
| } | |
| function hidePTOCards() { | |
| const cards = document.querySelectorAll('.cl-card'); | |
| let hid = 0; | |
| cards.forEach(card => { | |
| if (ptoCards.indexOf(card) >= 0) return; | |
| const desc = card.querySelector('.cl-form-control.cl-fake-input[data-cy="time-entry-description"]'); | |
| if (desc && desc.textContent.includes(PTO_DESCRIPTION)) { | |
| hid += 1; | |
| card.style.display = "none"; | |
| ptoCards.push(card); | |
| } | |
| }); | |
| //console.log("Hid", hid, "of", ptoCards.length, "cards"); | |
| return hid; | |
| } | |
| function addPTOToggle() { | |
| const submitLinks = Array.from( | |
| document.querySelectorAll('a[data-cy="submit-approval"]') | |
| ).filter(a => a.textContent.includes('Submit for approval')); | |
| //console.log("Found", submitLinks.length, "submit links"); | |
| if (!submitLinks.length || !ptoCards.length) return; | |
| let link = submitLinks[0]; | |
| if (link.nextSibling | |
| && link.nextSibling.classList | |
| && link.nextSibling.classList.contains('toggle-pto-btn') | |
| ) return; | |
| //console.log("Adding toggle button for", ptoCards.length, "PTO cards"); | |
| const btn = document.createElement('button'); | |
| btn.textContent = isHidden(ptoCards) ? "Show PTO" : "Hide PTO"; | |
| btn.className = 'toggle-pto-btn cl-small'; | |
| btn.style.marginLeft = '2em'; | |
| btn.addEventListener('click', () => { | |
| const hidden = isHidden(ptoCards); | |
| shouldHide = !hidden; | |
| ptoCards.forEach(card => { | |
| card.style.display = hidden ? "" : "none"; | |
| }); | |
| btn.textContent = hidden ? "Hide PTO" : "Show PTO"; | |
| }); | |
| link.parentNode.insertBefore(btn, link.nextSibling); | |
| } | |
| function isHidden(cards) { | |
| return cards.length && cards[0].style.display === "none"; | |
| } | |
| const observer = new MutationObserver(main); | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| //main(); // for debugging in console (uncomment this line and paste entire script into console) | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment