NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Timecamp Timeleft // @version 0.8.5 // @updateURL https://openuserjs.org/meta/PurelyImaginary/Timecamp_Timeleft.meta.js // @downloadURL https://openuserjs.org/src/scripts/PurelyImaginary/Timecamp_Timeleft.user.js // @author Purely Imaginary // @match https://www.timecamp.com/attendance // @grant none // ==/UserScript== (function() { function appendToUl(header,body){ var insertString = '<li class="pull-right"><div class="panel panel-success" style="margin:0">'; insertString += '<div class="panel-heading" style="padding: 5px;text-align: center;font-size: 0.8em;">'; insertString += header; insertString += '</div><div class="panel-body" style="padding: 5px;text-align: center;font-size: 0.8em;">'; insertString += body; insertString += '</div></div></li>'; $("ul.tt-report-nav").eq(0).append(insertString); } function stringToMinutes(string){ var data = string.split(" "); var returnVal = 0; if (data[0].includes(":")) { var split = data[0].split(":"); returnVal += parseInt(split[0])*60; if (string[0] == "-") split[1] = "-" + split[1]; returnVal += parseInt(split[1]); return parseInt(returnVal); } for (var i=0; i<data.length; i++){ var unit = data[i].substring(data[i].length-1,data[i].length); var amount = data[i].substring(0,data[i].length-1); if (unit == "h"){ returnVal += parseInt(amount*60); } else if (unit == "m"){ returnVal += parseInt(amount); } } if (string[0] == "-") returnVal = "-" + returnVal; return parseInt(returnVal); } function minutesToString(minutes){ var prefix = (minutes < 0) ? "-" : ""; var hours = Math.trunc(parseInt(minutes)/60); var remainingMinutes = Math.abs(parseInt(minutes) - (hours*60)); if (remainingMinutes < 10) remainingMinutes = "0" + remainingMinutes.toString(); return prefix + Math.abs(hours) + ":" + remainingMinutes; } function minutesToTCString(minutes){ var prefix = (minutes < 0) ? "-" : ""; var hours = Math.trunc(parseInt(minutes)/60); var remainingMinutes = Math.abs(parseInt(minutes) - (hours*60)); if (remainingMinutes < 10) remainingMinutes = "0" + remainingMinutes.toString(); return prefix + Math.abs(hours) + "h " + remainingMinutes + "m"; } $('.sub-list > li:first').before("<li id='breakdown' style='cursor:pointer; color:#dddddd'><strong>Breakdown</strong></li>"); $('#breakdown').on('click', function () { if ($("div:contains('Break now / all time')").length > 0 && ($("div:contains('Time Left')").length === 0)){ return; } var sumRow = $("tr:contains('%')"); sumRow = sumRow[sumRow.length-1]; var timeReq = 0; var enough = false; $("tr").each(function(data){ if ($(this).children()[3] !== undefined){ if ($(this).children()[3].innerHTML.indexOf("h") !== -1 && $(this).children()[3].innerHTML.indexOf("href") === -1 && $(this).children()[3].innerHTML.indexOf("Should") === -1 && $(this).children()[3].innerHTML.indexOf("%") === -1 && !enough){ timeReq += stringToMinutes($(this).children()[3].innerHTML); if ($(this).children()[6].innerHTML.indexOf("working") !== -1 ) { enough = true; } } } }); var paidSum = sumRow.children[9].innerHTML; paidSum = stringToMinutes(paidSum.substring(0,paidSum.indexOf("<"))); var activeRow = $("tr:contains('still')")[0]; if (activeRow !== undefined){ var widgetData = ""; var children = activeRow.children; var startTime = stringToMinutes(children[5].innerHTML); var timeAlreadyWorkedToday = stringToMinutes(children[9].children[0].innerHTML); var now = new Date(); var timeBehind = (startTime + timeAlreadyWorkedToday) - (stringToMinutes(now.toISOString().slice(11,16))+119); if ($("div:contains('Time Left')").length === 0){ var todayShouldBe = stringToMinutes(children[3].innerHTML); var workedWithoutToday = paidSum - timeAlreadyWorkedToday; var timeLeft = timeReq - workedWithoutToday; var todayTimeLeft = todayShouldBe - timeAlreadyWorkedToday; appendToUl("Work to do today",minutesToString(timeLeft) + " (" + minutesToString(timeLeft - todayShouldBe) + ")"); var leaveTime = startTime + timeLeft; var todayLeaveTime = startTime + todayShouldBe; if (todayLeaveTime < leaveTime){ appendToUl("Leave Between",minutesToString(todayLeaveTime) + " - " + minutesToString(leaveTime)); document.title = minutesToString(todayLeaveTime) + " - " + minutesToString(leaveTime); } else { appendToUl("Leave Between",minutesToString(leaveTime) + " - " + minutesToString(todayLeaveTime)); document.title = minutesToString(leaveTime) + " - " + minutesToString(todayLeaveTime); } var leaveDate = new Date(); var leaveDateSplit = minutesToString(leaveTime).split(":"); leaveDate.setHours(leaveDateSplit[0],leaveDateSplit[1],0,0); var timeleftInWork = leaveDate - now; var mLeft = Math.floor((timeleftInWork / 60000)); var leaveDateToday = new Date(); var leaveDateTodaySplit = minutesToString(todayLeaveTime).split(":"); leaveDateToday.setHours(leaveDateTodaySplit[0],leaveDateTodaySplit[1],0,0); var timeleftInWorkToday = leaveDateToday - now; var mLeftToday = Math.floor((timeleftInWorkToday / 60000)); if (mLeft < mLeftToday){ appendToUl("Time Left ("+timeBehind+"m)",minutesToString(mLeft) + " - " + minutesToString(mLeftToday)); } else { appendToUl("Time Left ("+timeBehind+"m)",minutesToString(mLeftToday) + " - " + minutesToString(mLeft)); } } else { //update Timeleft header $("div:contains('Time Left')")[4].innerHTML = "Time Left ("+timeBehind+"m)"; console.log("updated"); return; } } var rows = $("tr:contains(':'),tr:contains('am')"); var targetEff = 0.85; for (i=0;i<rows.length;i++){ var effectiveCell = rows[i].children[8].children[0]; var paidCell = rows[i].children[9].children[0]; var privCell = rows[i].children[10]; var effectiveTime = stringToMinutes(effectiveCell.innerHTML); var paidTime = stringToMinutes(paidCell.innerHTML); var effPercent = Math.round((effectiveTime/paidTime)*10000)/100; var maxPaidTime = effectiveTime / targetEff; var freeTimeLeft = maxPaidTime - paidTime; if (freeTimeLeft < 0) { var diff = paidTime - effectiveTime; freeTimeLeft = paidTime - (diff / (1 - targetEff)); } freeTimeLeft = minutesToString(freeTimeLeft); privCell.innerHTML = "<small>(" + effPercent + "%) " + freeTimeLeft + "</small>"; } if ($("th:contains('Private leave')")[0]){ $("th:contains('Private leave')")[0].innerHTML = "Efficiency (" + targetEff*100 + "%)"; } var effSum = sumRow.children[8].innerHTML; effSum = stringToMinutes(effSum.substring(0,effSum.indexOf("<"))); var maxPaidTimeSum = effSum / targetEff; var freeTimeLeftSum = maxPaidTimeSum - paidSum; if (freeTimeLeftSum < 0) { var diff = paidSum - effSum; freeTimeLeftSum = paidSum - (diff / (1 - targetEff)); } appendToUl("Break now / all time",freeTimeLeft + " / " + minutesToString(freeTimeLeftSum)); sumRow.children[10].innerHTML = minutesToTCString(freeTimeLeftSum) + "<br><small>" + Math.round((effSum/paidSum)*10000)/100 + "%</small>"; if ($("div.row") === undefined) { return; } $("div.row")[0].outerHTML = ""; for (i=0;i<8;i++){ $("div#reportContent")[0].children[0].outerHTML = ""; } $("ul.tt-report-nav")[0].children[2].outerHTML = ""; var temp = $("li:contains('Break now')")[0].outerHTML; $("li:contains('Break now')")[0].outerHTML = ""; $("li.filter-people").after(temp); $("h1:contains('Attendance')").eq(0).css("margin","0"); $("h1:contains('Attendance')").eq(0).css("margin-top","10px"); $('.bulk-dates').parent().parent().children().each(function(){$(this).css('line-height','0.5');}) $('.bulk-dates').each(function(){$(this).remove();}) }); })();