- // ==UserScript==
- // @name Keka Log Duration by Jp
- // @namespace http://tampermonkey.net/
- // @version 1.4
- // @description try to take over the world
- // @author You
- // @match https://ezeetechnosys.keka.com/
- // @icon https://www.google.com/s2/favicons?sz=64&domain=keka.com
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- (function () {
- 'use strict';
- const channel = new BroadcastChannel('keka-duration');
- let fistDuration;
- let secondDuration;
- let thirdDuration;
- let fourthDuration;
- let fifthDuration;
- function parseTime(timeStr) {
- const parts = timeStr.split(':');
- return parseInt(parts[0]) * 3600000 + parseInt(parts[1]) * 60000 + parseInt(parts[2]) * 1000;
- }
- let lastLogIndex=0;
-
- function calculateTotalDuration(duration1Str, duration2Str, duration3Str, duration4Str, duration5Str) {
- // Initialize total hours and minutes
- let totalHours = 0;
- let totalMinutes = 0;
-
- // Array of all duration strings
- const durations = [duration1Str, duration2Str, duration3Str, duration4Str, duration5Str];
-
- // Loop through each duration string
- durations.forEach(durationStr => {
- if (durationStr) { // Check if the duration string is not empty
- const [hours, minutes] = durationStr.match(/\d+/g).map(Number);
- totalHours += hours;
- totalMinutes += minutes;
- }
- });
-
- // Add overflow from minutes to hours
- totalHours += Math.floor(totalMinutes / 60);
- totalMinutes = totalMinutes % 60;
-
- // Format the total duration string
- const totalDurationStr = `${totalHours} Hr ${totalMinutes} Min`;
-
- return totalDurationStr;
- }
-
-
- function calculateDuration(startTimeSpan, endTimeSpan) {
- const startTimeStr = startTimeSpan.textContent.trim();
- const endTimeStr = endTimeSpan.textContent.trim();
-
- // If end time is empty, use current time
- const endTime = endTimeStr != "MISSING" ? endTimeStr : new Date().toLocaleTimeString('en-US', { hour12: true });
- console.log("TIMES", startTimeStr, endTime);
- // Parse time strings into Date objects
- const startTime = new Date(`2023-12-27 ${startTimeStr}`); // Assuming today's date
- const endTimeDate = new Date(`2023-12-27 ${endTime}`);
-
- // Calculate duration in milliseconds
- const durationMillis = endTimeDate.getTime() - startTime.getTime();
-
- // Convert milliseconds to hours and minutes
- const durationHours = Math.floor(durationMillis / (3600 * 1000));
- const durationMinutes = Math.floor((durationMillis % (3600 * 1000)) / (60 * 1000));
-
- // Formatted duration string
- const durationStr = `${durationHours} Hr ${durationMinutes} Min`;
-
- return durationStr;
- }
-
- function watchForModals() {
- const modals = document.querySelectorAll('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div');
- console.log("Modals", modals)
-
- modals.forEach(modal => {
-
- const modalsArray = Array.from(modals);
- const dayIndex = modalsArray.indexOf(modal) + 1; // Determine the day index (1, 2, or 3)
-
- const displaySpanXPath = `/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div/div[1]/span[1]`;
- const displaySpan = document.evaluate(
- displaySpanXPath,
- modal,
- null,
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
- null
- ).snapshotItem(0);
-
- const startTimeSpan = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[2]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const endTimeSpan = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[3]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const startTimeSpan1 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[2]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const endTimeSpan1 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[3]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const startTimeSpan2 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[3]/div[1]/div[2]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const endTimeSpan2 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[3]/div[1]/div[3]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const startTimeSpan3 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[4]/div[1]/div[2]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const endTimeSpan3 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[4]/div[1]/div[3]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const startTimeSpan4 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[5]/div[1]/div[2]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
- const endTimeSpan4 = document.evaluate(
- '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[5]/div[1]/div[3]/span[2]',
- modal,
- null,
- XPathResult.FIRST_ORDERED_NODE_TYPE,
- null
- ).singleNodeValue;
-
-
-
-
-
-
- if (startTimeSpan && endTimeSpan) {
- const durationStr = calculateDuration(startTimeSpan, endTimeSpan);
- fistDuration = durationStr
- const durationDisplaySpan = document.querySelector('.d-flex.align-items-center.ml-10');
-
- window.postMessage({ type: 'duration', value: durationStr }, '*');
- console.log("POSTED-DURATION")
- // Check for existing duration span:
- const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-1');
- if (!existingDurationSpan) {
- // Create span only if it doesn't exist
- const durationSpan = document.createElement('span');
- durationSpan.classList.add('duration-span-1'); // Add class for identification
- durationSpan.textContent = durationStr;
- durationSpan.style.fontWeight = 'bold';
- durationSpan.style.paddingLeft = '17px';
- durationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
- } else {
- console.log("Duration span already exists, skipping creation.");
- }
-
- var parentDivs = document.querySelectorAll('div.mb-30.ng-untouched.ng-pristine.ng-valid');
- if (parentDivs.length > 1) {
- // Targeting the second div as per your requirement
- var targetDiv = parentDivs[1];
- var pElement = targetDiv.querySelector('p.text-large'); // Assuming the span is the one you've added
- var spanElement = document.createElement('span');
- // Texts array for the morphing effect
- const texts = ["Log Duration", " By @Jaydeep😶"];
- let textIndex = 0;
-
- // Function to update the text with a morphing effect
- function updateText() {
- const nextText = texts[textIndex % texts.length];
- textIndex++;
-
- // Applying a fade-out effect
- spanElement.style.opacity = '0';
- spanElement.style.transition = 'opacity 0.5s ease-out';
-
- // After fade-out, change the text and fade it back in
- setTimeout(() => {
- spanElement.textContent = nextText;
-
- // Applying blur during transition
- spanElement.style.filter = 'blur(2px)';
- spanElement.style.opacity = '1';
- spanElement.style.transition = 'opacity 0.5s ease-in, filter 0.5s ease';
-
- // Removing blur after a moment
- setTimeout(() => {
- spanElement.style.filter = 'none';
- }, 500); // Match the transition time
- }, 500); // Wait for the fade-out to complete
- }
-
- // Starting the text update process
- spanElement.style.fontWeight = 'bold';
- spanElement.style.color = 'rgb(0, 123, 255)';
- spanElement.style.padding = '5px';
- spanElement.style.borderRadius = '5px';
- spanElement.style.fontSize = '16px';
- spanElement.style.marginLeft = '262px';
- spanElement.textContent = texts[textIndex % texts.length];
- textIndex++;
- pElement.appendChild(spanElement);
- setInterval(updateText, 2000);
- }
- }
-
- if (startTimeSpan1 && endTimeSpan1) {
- lastLogIndex = 1;
- console.log("11111111--11111", startTimeSpan1, endTimeSpan1)
- const durationStr = calculateDuration(startTimeSpan1, endTimeSpan1);
- secondDuration = durationStr;
- const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(2) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10');
- console.log("durationDisplaySpan", durationDisplaySpan)
-
- // Check for existing duration span:
- const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-2');
- if (!existingDurationSpan) {
- // Create span only if it doesn't exist
- const durationSpan = document.createElement('span');
- durationSpan.classList.add('duration-span-2'); // Add class for identification
- durationSpan.textContent = durationStr;
- durationSpan.style.fontWeight = 'bold';
- durationSpan.style.paddingLeft = '17px';
- durationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
- } else {
- console.log("Duration span already exists, skipping creation.");
- }
-
- }
- if (startTimeSpan2 && endTimeSpan2) {
- lastLogIndex = 2;
- console.log("11111111--11111", startTimeSpan2, endTimeSpan2)
- const durationStr = calculateDuration(startTimeSpan2, endTimeSpan2);
- thirdDuration = durationStr;
- const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(3) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10');
- console.log("durationDisplaySpan", durationDisplaySpan)
-
- // Check for existing duration span:
- const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-3');
- if (!existingDurationSpan) {
- // Create span only if it doesn't exist
- const durationSpan = document.createElement('span');
- durationSpan.classList.add('duration-span-3'); // Add class for identification
- durationSpan.textContent = durationStr;
- durationSpan.style.fontWeight = 'bold';
- durationSpan.style.paddingLeft = '17px';
- durationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
- } else {
- console.log("Duration span already exists, skipping creation.");
- }
-
- }
- if (startTimeSpan3 && endTimeSpan3) {
- lastLogIndex = 3;
- console.log("11111111--11111", startTimeSpan3, endTimeSpan3)
- const durationStr = calculateDuration(startTimeSpan3, endTimeSpan3);
- fourthDuration = durationStr;
- const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(3) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10');
- console.log("durationDisplaySpan", durationDisplaySpan)
-
- // Check for existing duration span:
- const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-3');
- if (!existingDurationSpan) {
- // Create span only if it doesn't exist
- const durationSpan = document.createElement('span');
- durationSpan.classList.add('duration-span-3'); // Add class for identification
- durationSpan.textContent = durationStr;
- durationSpan.style.fontWeight = 'bold';
- durationSpan.style.paddingLeft = '17px';
- durationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
- } else {
- console.log("Duration span already exists, skipping creation.");
- }
-
- }
- if (startTimeSpan4 && endTimeSpan4) {
- lastLogIndex = 4;
- console.log("11111111--11111", startTimeSpan4, endTimeSpan4)
- const durationStr = calculateDuration(startTimeSpan4, endTimeSpan4);
- fifthDuration = durationStr;
- const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(4) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10');
- console.log("durationDisplaySpan", durationDisplaySpan)
-
- // Check for existing duration span:
- const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-4');
- if (!existingDurationSpan) {
- // Create span only if it doesn't exist
- const durationSpan = document.createElement('span');
- durationSpan.classList.add('duration-span-4'); // Add class for identification
- durationSpan.textContent = durationStr;
- durationSpan.style.fontWeight = 'bold';
- durationSpan.style.paddingLeft = '17px';
- durationSpan.style.color = 'darkred';
- durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
- } else {
- console.log("Duration span already exists, skipping creation.");
- }
-
- }
- if(lastLogIndex) {
-
- const totaldurationDisplaySpan = document.querySelector(`body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(${lastLogIndex+1}) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid`);
- console.log(fistDuration, secondDuration,"3",thirdDuration,'4',fourthDuration,'5',fifthDuration, "#################111")
- const total = calculateTotalDuration(
- fistDuration,
- startTimeSpan1 ? secondDuration : 0,
- startTimeSpan2 ? thirdDuration : 0,
- startTimeSpan3 ? fourthDuration : 0,
- startTimeSpan4 ? fifthDuration : 0
- );
- console.log("total", total)
-
- // Check for existing total duration span:
- const existingTotalDurationSpan = totaldurationDisplaySpan.querySelector('.total-duration-span');
- if (!existingTotalDurationSpan) {
- // Create span only if it doesn't exist
- const TotaldurationSpan = document.createElement('span'); // Added closing parenthesis
- TotaldurationSpan.classList.add('total-duration-span'); // Add class for identification
- TotaldurationSpan.textContent = total;
- TotaldurationSpan.style.fontWeight = 'bold';
- // TotaldurationSpan.style.paddingLeft = '17px';
- TotaldurationSpan.style.color = '#0600ff';
- TotaldurationSpan.style.float = 'right';
- TotaldurationSpan.style.padding = '5px';
- TotaldurationSpan.style.background = 'lightblue';
- TotaldurationSpan.style.marginRight = '150px';
- TotaldurationSpan.style.borderRadius = '5px';
- TotaldurationSpan.style.borderTop = '3px solid #888'
- totaldurationDisplaySpan.insertAdjacentElement('afterend', TotaldurationSpan);
-
- }
- }
-
-
-
- })
- };
-
-
-
-
- const observer = new MutationObserver(mutations => {
- console.log("Observing.....")
- const modalTriggerElements = document.querySelectorAll('employee-attendance-list-view .attendance-logs-row');
- modalTriggerElements.forEach(element => {
- element.addEventListener('click', watchForModals);
- });
- });
-
- observer.observe(document.body, { childList: true, subtree: false });
-
- })(); // Closed parenthesis for the immediately invoked function expression