NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Attendo_ba_daily_work_time_extended
// @namespace http://tampermonkey.net/
// @version 0.38
// @license MIT
// @description Add missing work timer for current day to attendo.ba. Extended with monthly summary and daily pause display.
// @author Bootta
// @match https://attendo.ba/attendo/app/entry
// @require https://code.jquery.com/jquery-3.3.1.min.js
// @updateURL https://openuserjs.org/meta/Bootta11/Attendo_ba_daily_work_time_extended.meta.js
// ==/UserScript==
(function () {
'use strict';
let entries_refresh_interval_in_seconds = 300;
let enable_time_without_pause = true;
let $ = window.jQuery;
let worklog_entries;
let checkedout_time_periods_sum = 0;
let open_time_period_start;
let mandatory_break = 30 * 60 * 1000;
let mandatory_break_left = mandatory_break;
let meal_break_sum = 0;
let refresh_enteries_interval;
let today = new Date();
let dd = today.getDate();
let mm = today.getMonth() + 1; //January is 0!
let yyyy = today.getFullYear();
let today_datetime_string = yyyy + '-' + aln(mm) + '-' + aln(dd);
let daily_work_time_element = `
<li id="daily_work_timer_holder" >
<a href="#" onclick="return false" disabled id='daily_time_holder' style="hidden:true">
Today worked: <big><span id="daily_work_timer" style="color: black"></span></big>
</a>
<a href="#" onclick="return false" disabled id='plus_minus_holder' style='hidden:true'>
<span id="plus_or_minus"></span><big><span style="color: black" id='plus_minus_timer'></span></big>
</a>
</li>`;
let plus_minus_worked_ms = 0;
let cumulative_daily_time, previous_cumulative_daily_time = 0;
let wanted_time = 0;
let timer_is_running = false;
refreshEnteries(function () {
getMonthlySummary();
});
refresh_enteries_interval = setInterval(refreshEnteries, 1000 * entries_refresh_interval_in_seconds);
setInterval(refreshDailyWorkTime, 1000);
$('.navbar .navbar-right').prepend(daily_work_time_element);
$('#daily_time_holder').mouseenter(function () {
$('#daily_time_holder').hide();
$('#plus_minus_holder').show();
$('#plus_minus_holder').css('width', '350px');
$('#plus_minus_holder').attr('align', 'center');
})
$('#plus_minus_holder').mouseout(function (event) {
if ($.contains(this, event.relatedTarget) || this == event.relatedTarget) {
return;
}
$('#daily_time_holder').show();
$('#daily_time_holder').css('width', '350px')
$('#daily_time_holder').css('text-align', 'center')
$('#daily_time_timer').css('display', 'block')
$('#plus_minus_holder').hide();
})
$('#plus_minus_holder').hide();
function refreshDailyWorkTime() {
if (worklog_entries) {
cumulative_daily_time = checkedout_time_periods_sum;
if (open_time_period_start) {
let open_time_period_current_datetime = new Date();
cumulative_daily_time += Math.abs(open_time_period_current_datetime - open_time_period_start);
}
let cumulative_daily_time_without_pause = cumulative_daily_time - (1000 * 60 * 30);
//console.log(tsToDisplayTime(plus_minus_worked_ms), tsToDisplayTime(cumulative_daily_time), tsToDisplayTime(wanted_time), tsToDisplayTime(mandatory_break_left), timer_is_running, tsToDisplayTime(cumulative_daily_time - wanted_time - mandatory_break_left),tsToDisplayTime(plus_minus_worked_ms));
let monthly_time = plus_minus_worked_ms + (timer_is_running ? (cumulative_daily_time - wanted_time - mandatory_break_left) : 0);
$('#plus_minus_timer').text(tsToDisplayTime(monthly_time));
$('#plus_or_minus').html('Monthly (' + (plus_minus_worked_ms >= 0 ? 'plus: ' : 'minus: ') + tsToDisplayTime(plus_minus_worked_ms) + '): ');
var seconds = Math.floor(((cumulative_daily_time % (1000 * 60)) / 1000));
var minutes = Math.floor(((cumulative_daily_time % (1000 * 60 * 60)) / (1000 * 60)));
var hours = Math.floor((cumulative_daily_time / (1000 * 60 * 60)));
let display_time = tsToDisplayTime(cumulative_daily_time);
let mandatory_minutes = Math.floor(((mandatory_break_left % (1000 * 60 * 60)) / (1000 * 60)));
let mandatory_seconds = Math.floor(((mandatory_break_left % (1000 * 60)) / 1000));
display_time += (enable_time_without_pause ? '(-' + (aln(mandatory_minutes) + ' : ' + aln(mandatory_seconds)) + 'min)' : '');
$('#daily_work_timer').text(display_time);
previous_cumulative_daily_time = cumulative_daily_time;
}
}
function refreshEnteries(callback) {
checkedout_time_periods_sum = 0;
$.get('https://attendo.ba/attendo/app/api/employee/overview/daily?date=' + today_datetime_string, function (data) {
worklog_entries = data.entries;
if (data.calculation && data.calculation.summary && data.calculation.summary.wantedTime) {
wanted_time = parsePTInterval(data.calculation.summary.wantedTime);
}
if (worklog_entries && worklog_entries.length > 0) {
for (let i = 0; i < worklog_entries.length; i++) {
let entry = worklog_entries[i];
if (entry.entryType == "CHECK_IN") {
let check_in_start_datetime = new Date(entry.dateTime);
let check_in_end_datetime = new Date();
if (worklog_entries[i + 1]) {
check_in_end_datetime = new Date(worklog_entries[i + 1].dateTime);
checkedout_time_periods_sum += Math.abs(check_in_end_datetime - check_in_start_datetime);
}
else {
open_time_period_start = check_in_start_datetime;
}
}
else if (entry.entryType == "MEAL_BREAK") {
let meal_break_start_datetime = new Date(entry.dateTime);
let meal_break_end_datetime = new Date();
if (worklog_entries[i + 1]) {
meal_break_end_datetime = new Date(worklog_entries[i + 1].dateTime);
meal_break_sum += Math.abs(meal_break_end_datetime - meal_break_start_datetime);
if (meal_break_sum <= mandatory_break) {
mandatory_break_left -= meal_break_sum;
}
else {
mandatory_break_left = 0;
}
}
}
}
if (open_time_period_start) {
timer_is_running = true;
}
let cumulative_daily_time_without_pause = checkedout_time_periods_sum - (1000 * 60 * 30);
}
else {
mandatory_break_left = 0;
}
callback();
});
}
//add leading null
function aln(n) {
return (n < 10 ? '0' + n : n);
}
// timestamp to time
function tsToDisplayTime(ts) {
let minus = '';
if (ts < 0) {
minus = '-';
ts = ts * -1;
}
var seconds = Math.floor(((ts % (1000 * 60)) / 1000));
var minutes = Math.floor(((ts % (1000 * 60 * 60)) / (1000 * 60)));
var hours = Math.floor((ts / (1000 * 60 * 60)));
return minus + aln(hours) + ' : ' + aln(minutes) + ' : ' + aln(seconds);
}
function parsePTInterval(pt_interval) {
var reptms = /^PT(?:([0-9\-]+)H)?(?:([0-9\-]+)M)?(?:([0-9\-]+)S)?$/;
let hours = 0,
minutes = 0,
seconds = 0,
totalseconds = 0;
if (reptms.test(pt_interval)) {
var matches = reptms.exec(pt_interval);
if (matches[1]) hours = Number(matches[1]);
if (matches[2]) minutes = Number(matches[2]);
if (matches[3]) seconds = Number(matches[3]);
totalseconds = hours * 3600 + minutes * 60 + seconds;
}
return totalseconds * 1000;
}
function getMonthlySummary() {
var date = new Date();
var firstDayOfMonth = formatDateForQuery(new Date(date.getFullYear(), date.getMonth(), 1));
var lastDayOfMonth = formatDateForQuery(new Date(date.getFullYear(), date.getMonth() + 1, 0));
$.get('https://attendo.ba/attendo/app/api/employee/overview/period?page=0&size=40&fromDate=' + firstDayOfMonth + '&toDate=' + lastDayOfMonth, function (data) {
for (let i = 0; i < data.rows.length; i++) {
if (timer_is_running && i == (data.rows.length - 1)) {
continue;
}
plus_minus_worked_ms += parsePTInterval(data.rows[i].calculation.summary.difference);
}
});
}
function formatDateForQuery(input_date) {
let dd = input_date.getDate();
let mm = input_date.getMonth() + 1; //January is 0!
let yyyy = input_date.getFullYear();
return yyyy + '-' + aln(mm) + '-' + aln(dd);
}
})();