Skip to content

Instantly share code, notes, and snippets.

@millerdev
Last active May 31, 2017 18:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save millerdev/96c9b824b8902d4a5c19 to your computer and use it in GitHub Desktop.
Save millerdev/96c9b824b8902d4a5c19 to your computer and use it in GitHub Desktop.
A Greasemonkey script to calculate and display hours logged on FogBugz timesheet popup.
// ==UserScript==
// @name FogBugz Timesheet Hours
// @namespace fb-ts-hours
// @description Calculate and display hours worked on FogBugz timesheet popup.
// https://gist.github.com/millerdev/96c9b824b8902d4a5c19
// @include http://manage.dimagi.com/*
// @include https://manage.dimagi.com/*
// @version 1
// @grant none
// @run-at document-start
// ==/UserScript==
function main() {
function calculateTimeWorked(table) {
function date(value) {
return new Date(TODAY + " " + value);
}
var NOW = new CTZNow(),
TODAY = NOW.toDateString(),
MINUTE = 60000,
totalMinutes = 0,
minutes;
$.each(table.find("tr.row"), function(i, row) {
var cells = $(row).find("td"),
start = $("nobr", cells.get(2)).text(),
end = $("nobr", cells.get(3)).text(),
diff;
if (end === "Stop Work") {
diff = (NOW - date(start)) / MINUTE;
} else {
diff = (date(end) - date(start)) / MINUTE;
}
totalMinutes = totalMinutes + diff;
});
minutes = Math.floor(totalMinutes % 60);
if (minutes < 10) {
minutes = "0" + minutes;
}
return Math.floor(totalMinutes / 60) + ":" + minutes;
}
function setTimeWorked() {
var table = $("#idTimesheetTable"),
timeWorked = calculateTimeWorked(table),
footer = $("#FBTH_timeWorked");
if (footer.length === 0) {
footer = $("<span id='FBTH_timeWorked' style='margin-left: 6em;'>");
table.find("tr.row:last").next().find("th").append(footer);
}
footer.text(timeWorked);
}
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var config = { childList: true, subtree: true };
/**
* Setup observer to invoke callback when child element is added to parent.
*
* Disconnect observer if callback returns true.
*/
function onAddNode(child, parent, callback) {
$(parent).each(function (x, target) {
//console.log(target);
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
var nodes = mutation.addedNodes;
//console.log(nodes);
if (nodes && $(nodes).is(child)) {
if (callback(nodes)) {
observer.disconnect();
};
}
});
});
observer.observe(target, config);
});
}
onAddNode("#idTimesheetTable", "body", function() {
setTimeWorked();
// setup new observer on parent of #idTimesheetTable
var parent = $("#idTimesheetTable").parent();
onAddNode("#idTimesheetTable", parent, setTimeWorked);
return true; // disconnect body observer (it's inefficient)
});
// Make the previous/next day buttons easier to click
onAddNode("#idTimesheetTable", "body", function() {
$('#timeclockPopup').css('top', '155px');
$('#idTimesheetPrevious').css('padding', '.5em');
$('#prevTimesheetButton').css('padding', '.5em');
$('#idTimesheetNext').css('padding', '.5em');
return true;
});
}
window.addEventListener('load', function() {
if(typeof $ === 'undefined') {
// load jQuery : http://stackoverflow.com/a/4261831/10840
var script = document.createElement("script");
script.setAttribute("src", "//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js");
script.addEventListener('load', function() {
var script = document.createElement("script");
script.textContent = "window.jQ=jQuery.noConflict(true);(" + main.toString() + ")();";
document.body.appendChild(script);
}, false);
document.body.appendChild(script);
} else {
main();
}
});
@millerdev
Copy link
Author

Installation

Firefox

  • Install Greasemonkey. Be sure to restart your browser to complete the installation when prompted.
  • Click the Raw button above the script on this page. You should see a Greasemonkey Installation dialog.
  • Click Install.

Chrome

  • Install Tampermonkey
  • Click the Raw button above the script on this page. Tampermonkey should prompt you to install the script.
  • Click Install.

Reload FogBugz after installing the script. Click Working On > Edit Timesheet. You should see total number of hours logged at the bottom of the table beside Add Interval.

Enjoy!

@millerdev
Copy link
Author

Known issues

  • If your FogBugz timezone setting is different from your computer's timezone and you've got an uncompleted timesheet record, then the total time will be incorrect.

@esoergel
Copy link

Made a slight unrelated addition to make the forward and back buttons actually usable in FF: https://gist.github.com/esoergel/e49b316d9d3d04927a4e#file-fogbugz_timesheet_hours-user-js-L84-L91

@millerdev
Copy link
Author

@esoergel updated to use CTZNow and easier-to-click previous/next day buttons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment