emptydev / Closer - TR - Horas

// ==UserScript==
// @name         Closer - TR - Horas
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  Draw grid with usefull data
// @author       2022, Emanuel Almeida (https://openuserjs.org/users/emptydev)
// @match        https://portal.closer.pt/Pages/TimeReports/default.aspx
// @icon         https://www.google.com/s2/favicons?sz=64&domain=closer.pt
// @grant        none
// @updateURL https://openuserjs.org/meta/emptydev/Closer_-_TR_-_Horas.meta.js
// @downloadURL https://openuserjs.org/install/emptydev/Closer_-_TR_-_Horas.user.js
// @copyright 2022, Emanuel Almeida (https://openuserjs.org/users/emptydev)
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let currentUserName = '';

    function bindUserNameGet() {
        $("img[src*='edit.png'], img[src*='view.png']").on("click", function() {
            currentUserName = $(this).closest("tr").find("td:eq(0)").text();
        });
    }

    function formatSeconds(numberOfMinutes) {
        //create duration object from moment.duration
        var duration = moment.duration(numberOfMinutes, 'minutes');

        //calculate hours
        var hh = (duration.years()*(365*24)) + (duration.months()*(30*24)) + (duration.days()*24) + (duration.hours());

        //get minutes
        var mm = duration.minutes();

        //return total time in hh:mm format
        return (hh < 10 ? "0"+hh : hh)+':'+(mm < 10 ? "0"+mm : mm);
    }

    function getWeekDay(number) {
        switch(number) {
            case 0:
                return "Domingo";
                break;
            case 1:
                return "Segunda";
                break;
            case 2:
                return "Terça";
                break;
            case 3:
                return "Quarta";
                break;
            case 4:
                return "Quinta";
                break;
            case 5:
                return "Sexta";
                break;
            case 6:
                return "Sábado";
                break;
            default:
                return "";
        }
    }

    let processData = false;
    let vacations = [];

    $(document).ajaxComplete(function(a,b,c) {
        bindUserNameGet();

        function applyClick() {
            $("#TABLE_TimeReports").find("img[src*='edit.png'], img[src*='view.png']").on("click", function() {
                const editUser = $(this).closest("tr").find("td:eq(0)").text().trim();
                localStorage.setItem("editUser", editUser);
            });
        }
        applyClick();

        $(".paginate_button").on("click", function() {
            setTimeout(function() {
                applyClick();
                bindUserNameGet();
            });
        });

        $("div > input[src*='vacationsViewIcon.png']").on("click", function() {
            localStorage.setItem("editUser", $("#LbluserName").text().trim());
        });

        if(c.url.indexOf("GetProjectPhases") > -1) {
            const button = $("<input type='button' value='Carregar Horas' class='actionButton accept-button' />");
            const tablecontainer = $("<div class='contentForm2' style='float:left; width:100%; padding: 0; box-sizing: border-box;'></div>");
            const container = $("<div id='contentForm' class='contentForm1' style='float:left; width:100%; padding: 6px 6px 40px 6px; box-sizing: border-box;'></div>").append(button, tablecontainer);
            const table = $("<table id='trHoras' class='DataTable dataTable'><thead></thead><tbody></tbody><tfoot><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tfoot></table>");
            let datatable;

            $("#TimeReports").append(container);

            button.on("click", function() {
                $("#loader").show();

                if(datatable)
                    datatable.destroy();

                $("#trHoras").remove();
                $(".contentForm2").html("");

                setTimeout(function() {
                    let trData = [];

                    $("table#calendarTable td[id]").map(function(idx) {
                        const tdId = $(this).attr("id");
                        $.ajax({
                            type: "POST",
                            url: "../../ScriptServices/DataService.asmx/GET_TimeReportDailyLog_Task_ByDailyLogID",
                            data: `{pk_id:'${tdId}'}`,
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",
                            success: function(data) {
                                trData = trData.concat(data.d);
                            },
                            async: false
                        });
                    });

                    $("#loader").hide();

                    if(trData && trData.length > 0) {
                        $(".contentForm2").append(table);

                        datatable = $("#trHoras").DataTable({
                            language: {
                                processing: "A processar...",
                                lengthMenu: "_MENU_",
                                zeroRecords: "Não foram encontrados resultados",
                                info: "_TOTAL_ registos",
                                infoEmpty: " ",
                                infoFiltered: " ",
                                infoPostFix: "",
                                search: "Procurar: ",
                                url: "",
                                paginate: {
                                    first: "Primeiro",
                                    previous: "Anterior",
                                    next: "Seguinte",
                                    last: "Último"
                                }
                            },
                            dom: 'BFlfrtip',
                            buttons: [{
                                extend: "excelHtml5",
                                text: "Excel",
                                footer: false,
                                header: true,
                                title:'',
                                filename: currentUserName+"_"+moment().format("YYYYMMDD-HHmmss"),
                                exportOptions: {
                                    columns: ":visible"
                                }
                            }],
                            paginationType: "full_numbers",
                            data: trData,
                            order: [[0, 'asc'], [4, 'asc']],
                            "footerCallback": function ( row, data, start, end, display ) {
                                var api = this.api();

                                // Remove the formatting to get integer data for summation
                                var intVal = function(i) {
                                    return typeof i === 'string' ? (parseInt(i.split(":")[0])*60+parseInt(i.split(":")[1])) : typeof i === 'number' ? i : 0;
                                }

                                // Total over all pages
                                var total = api
                                .column( 6 )
                                .data()
                                .reduce( function (a, b) {
                                    return intVal(a) + intVal(b);
                                }, 0 );

                                // Total over this page
                                var pageTotal = api
                                .column( 6, { search: 'applied' } )
                                .data()
                                .reduce( function (a, b) {
                                    return intVal(a) + intVal(b);
                                }, 0 );

                                // Update footer
                                $( api.column( 6 ).footer() ).html("<b>"+formatSeconds(pageTotal) + "</b> ("+ formatSeconds(total) + ")");
                            },
                            columns:[{
                                data:"Date",
                                title:"Data",
                                render: function(a,b,c) {
                                    const _date = moment(parseInt(a.match(/(\d+)/)[0]))
                                    return _date.format("DD/MM/YYYY") + " - " + getWeekDay(_date.day());
                                }
                            }, {
                                data: "ProjectName",
                                title:"Projeto"
                            }, {
                                data: "ProjectPhaseName",
                                title:"Fase"
                            }, {
                                data: "TaskName",
                                title:"Tarefa"
                            }, {
                                data: "StartTime",
                                title:"Início"
                            }, {
                                data: "EndTime",
                                title:"Fim"
                            }, {
                                data: "DateDiff",
                                title:"Tempo total"
                            }, {
                                data: "Task_Type_description",
                                title:"Tipo Horas",
                                width:"30%"
                            }]
                        });
                    }
                });
            });
        }

        if(c.url.indexOf("GET_VacationsInformation_ByUserIDAndYear") > -1) {
            const currentUser = JSON.parse(c.data);
            if(currentUser.userIDString) {
                localStorage.setItem("userIDString", currentUser.userIDString);
            }
        }

        if(c.url.indexOf("GET_Vacations_ByUserIDAndYear") > -1) {
            const button = $("<input type='button' value='Carregar Férias' class='actionButton accept-button' />");
            const tablecontainer = $("<div class='contentForm2' style='float:left; width:100%; padding: 0; box-sizing: border-box;'></div>");
            const container = $("<div id='contentForm' class='contentForm1' style='float:left; width:100%; margin-top:5px; padding: 6px 6px 40px 6px; box-sizing: border-box;'></div>").append(button, tablecontainer);
            const table = $("<table id='trVacations' class='DataTable dataTable'><thead></thead><tbody></tbody></table>");
            let datatable;

            $("#Holidays").append(container);

            button.on("click", function() {
                $("#loader").show();

                processData = false;
                vacations = [];

                if(datatable)
                    datatable.destroy();

                $("#trVacations").remove();
                $(".contentForm2").html("");

                setTimeout(function() {
                    const currentDay = moment().format("YYYY");
                    const currentUser = localStorage.getItem("userIDString");

                    if(!processData) {
                        processData = true;
                        for(let i = 2010; i <= currentDay; i++) {
                            $.ajax({
                                type: "POST",
                                url: "../../ScriptServices/DataService.asmx/GET_VacationsInformation_ByUserIDAndYear",
                                data: `{"userIDString":"${currentUser}","yearString":"${i}"}`,
                                contentType: "application/json; charset=utf-8",
                                dataType: "json",
                                success: function(data) {
                                    if(data.d.UserBookedDays > 0 || data.d.UserRemainingVacationDays > 0 || data.d.UserUsedVacationDays > 0) {
                                        vacations.push($.map(data, function(e) {
                                            const total = e.UserBookedDays+e.UserRemainingVacationDays+e.UserUsedVacationDays;
                                            return {UserBookedDays: e.UserBookedDays, UserRemainingVacationDays: e.UserRemainingVacationDays, UserUsedVacationDays: e.UserUsedVacationDays, Total: total, Year: i }
                                        })[0]);
                                    }
                                },
                                async: false
                            });
                        }

                        $("#loader").hide();

                        if(vacations && vacations.length > 0) {
                            $(".contentForm2").append(table);

                            datatable = $("#trVacations").DataTable({
                                language: {
                                    processing: "A processar...",
                                    lengthMenu: "_MENU_",
                                    zeroRecords: "Não foram encontrados resultados",
                                    info: "_TOTAL_ registos",
                                    infoEmpty: " ",
                                    infoFiltered: " ",
                                    infoPostFix: "",
                                    search: "Procurar: ",
                                    url: "",
                                    paginate: {
                                        first: "Primeiro",
                                        previous: "Anterior",
                                        next: "Seguinte",
                                        last: "Último"
                                    }
                                },
                                dom: 'BFlfrtip',
                                buttons: [{
                                    extend: "excelHtml5",
                                    text: "Excel",
                                    footer: false,
                                    header: true,
                                    title:'',
                                    filename: localStorage.getItem("editUser")+"_"+moment().format("YYYYMMDD-HHmmss"),
                                    exportOptions: {
                                        columns: ":visible"
                                    }
                                }],
                                paginationType: "full_numbers",
                                data: vacations,
                                order: [0, 'asc'],
                                columns:[ {
                                    data: "Year",
                                    title:"Ano",
                                    width:"20%"
                                }, {
                                    data: "UserBookedDays",
                                    title:"Férias Marcadas",
                                    width:"22.5%"
                                }, {
                                    data: "UserRemainingVacationDays",
                                    title:"Férias por Marcar",
                                    width:"22.5%"
                                }, {
                                    data: "UserUsedVacationDays",
                                    title:"Férias Gozadas",
                                    width:"22.5%"
                                }, {
                                    data: "Total",
                                    title:"Total",
                                    width:"22.5%"
                                }]
                            });
                        }
                    }
                });
            });
        }
    });
})();