您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds the information about required vs worked hours in Tempo.io
// ==UserScript== // @name JIRA Hours Diff // @namespace https://github.com/lovromazgon // @version 0.2.3 // @description Adds the information about required vs worked hours in Tempo.io // @author Lovro Mažgon // @match https://app.tempo.io/timesheets/jira/reports/* // @grant none // ==/UserScript== var loadedHoursWorked = false; var loadedHoursRequired = false; var hoursWorked = 0; var hoursRequired = 0; var hoursDiff = 0; var hoursRequiredDiv = null; var hoursDiffDiv = null; (function(open) { XMLHttpRequest.prototype.open = function() { this.addEventListener("readystatechange", function() { if (this.readyState == 4 && this.responseURL == 'https://app.tempo.io/rest/tempo-timesheets/4/worklogs/search') { mainWorklogs(JSON.parse(this.response)); } else if (this.readyState == 4 && this.responseURL == 'https://app.tempo.io/rest/tempo-timesheets/4/private/days/search') { mainDays(JSON.parse(this.response)[0].days); } }, false); open.apply(this, arguments); }; })(XMLHttpRequest.prototype.open); function mainWorklogs(worklogs) { var secondsWorked = 0; for (i = 0; i < worklogs.length; i++) { secondsWorked += worklogs[i].timeSpentSeconds; } hoursWorked = secondsToHours(secondsWorked); loadedHoursWorked = true; main(); } function mainDays(days) { var secondsRequired = 0; for (i = 0; i < days.length; i++) { secondsRequired += days[i].requiredSeconds; } hoursRequired = secondsToHours(secondsRequired); loadedHoursRequired = true; main(); } function main() { if (!loadedHoursRequired || !loadedHoursWorked) { return; } hoursDiff = Math.round((hoursWorked - hoursRequired) * 10) / 10; console.log('I worked ' + hoursWorked + ' hours'); console.log('I should have worked ' + hoursRequired + ' hours'); console.log('Difference is ' + hoursDiff + ' hours'); var headerActions = getHeaderActions(); displayHoursRequired(headerActions); displayHoursDiff(headerActions); } function getHeaderActions() { var el = document.getElementsByClassName('tempo-header-wrapper')[0]; var childIndex = 1; // in the first round use 1 to get the second element while (true) { var child = null; if (el.children.length === 0) { // no children break; } else if (el.children.length == 1) { // if it is the only child use it child = el.children[0]; } else { // in the first round use 1 to get the second element // all other rounds use 0 to get the first element child = el.children[childIndex]; childIndex = 0; } if (child.tagName == 'DIV') { el = child; } else { break; } } return el; } function displayHoursRequired(headerActions) { if (!hoursRequiredDiv) { hoursRequiredDiv = headerActions.lastChild.cloneNode(true); headerActions.appendChild(hoursRequiredDiv); } hoursRequiredDiv.innerHTML = ' / ' + hoursRequired + 'h'; hoursRequiredDiv.style.color = 'grey'; hoursRequiredDiv.style.margin = '0 5px'; } function displayHoursDiff(headerActions) { if (!hoursDiffDiv) { hoursDiffDiv = headerActions.lastChild.cloneNode(true); headerActions.appendChild(hoursDiffDiv); } var sign; var color; if (hoursDiff >= 0) { sign = '+'; color = 'green'; } else { sign = ''; color = 'red'; } hoursDiffDiv.innerHTML = ' (' + sign + hoursDiff + ')'; hoursDiffDiv.style.color = color; } function secondsToHours(seconds) { return Math.round(seconds / 60 / 60 * 10) / 10; }