NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Harvest - Hourly Pay // @namespace https://zachhardesty.com // @author Zach Hardesty <zachhardesty7@users.noreply.github.com> (https://github.com/zachhardesty7) // @description adds total money made per day and week to Harvest (excl. taxes) // @copyright 2019, Zach Hardesty (https://zachhardesty.com/) // @license GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt // @version 1.0.2 // @homepageURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/harvest-hourly-pay.user.js // @homepageURL https://openuserjs.org/scripts/zachhardesty7/Harvest_-_Hourly_Pay // @supportURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/issues // @updateURL https://openuserjs.org/meta/zachhardesty7/Harvest_-_Hourly_Pay.meta.js // @downloadURL https://openuserjs.org/src/scripts/zachhardesty7/Harvest_-_Hourly_Pay.user.js // @match https://*.harvestapp.com/* // ==/UserScript== /** * @param {string} t - hh:mm * @returns {number} parsed time */ function timeToDecimal(t) { const splitTime = t.split(":") return Number.parseFloat(splitTime[0]) + Number.parseFloat(splitTime[1]) / 60 } ;(function harvestPay() { function addPay() { // ** hourly pay rate - replace this ** const rate = 16 const hoursPerDay = document.querySelectorAll( ".day-view-week-nav li a span" ) for (const time of hoursPerDay) { if (!time.textContent.includes("$")) { /* eslint-disable-next-line no-param-reassign */ time.textContent += ` | $${Math.round( timeToDecimal(time.textContent) * rate )}` } } const hoursPerWeek = document.querySelector( "#day-view-week-nav-total .test-week-total" ) if (!hoursPerWeek.textContent.includes("$")) { hoursPerWeek.textContent += ` | $${Math.round( timeToDecimal(hoursPerWeek.textContent) * rate )}` } } const observeDOM = (() => { const MutationObserver = window.MutationObserver || window.WebKitMutationObserver const eventListenerSupported = window.addEventListener return (obj, callback) => { if (MutationObserver) { // define a new observer const obs = new MutationObserver((mutations) => { if ( mutations[0].addedNodes.length || mutations[0].removedNodes.length ) { callback() } }) // have the observer observe foo for changes in children obs.observe(obj, { childList: true, subtree: true }) } else if (eventListenerSupported) { obj.addEventListener("DOMNodeInserted", callback, false) obj.addEventListener("DOMNodeRemoved", callback, false) } } })() // Observe a specific DOM el for node changes: observeDOM(document.querySelector(".day-view-week-nav"), addPay) addPay() // Execute on page load })()