From b09e4938b788aa373eab86b514ff97e6ad4e013f Mon Sep 17 00:00:00 2001 From: Flos Date: Sat, 1 Nov 2025 23:23:25 +0100 Subject: [PATCH] Fix ticket timer, to initialise on reload and after tab sleeping When the tab was reloaded, the timer was not initialized again. When the tab was in background and the tab was sleeping, the timer showed the wrong time --- agent/js/ticket_time_tracking.js | 141 ++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 49 deletions(-) diff --git a/agent/js/ticket_time_tracking.js b/agent/js/ticket_time_tracking.js index ea1b69f8..6287d6d8 100644 --- a/agent/js/ticket_time_tracking.js +++ b/agent/js/ticket_time_tracking.js @@ -1,6 +1,5 @@ (function() { document.addEventListener("DOMContentLoaded", function() { - // Initialize variables var timerInterval = null; var ticketID = getCurrentTicketID(); var elapsedSecs = getElapsedSeconds(); @@ -22,6 +21,10 @@ return pausedTime + timeSinceStart; } + function pad(val) { + return val < 10 ? "0" + val : val; + } + function displayTime() { let totalSeconds = elapsedSecs; let hours = Math.floor(totalSeconds / 3600); @@ -29,17 +32,21 @@ let minutes = Math.floor(totalSeconds / 60); let seconds = totalSeconds % 60; - document.getElementById("hours").value = pad(hours); - document.getElementById("minutes").value = pad(minutes); - document.getElementById("seconds").value = pad(seconds); - } + let hoursEl = document.getElementById("hours"); + let minutesEl = document.getElementById("minutes"); + let secondsEl = document.getElementById("seconds"); - function pad(val) { - return val < 10 ? "0" + val : val; + if (hoursEl && minutesEl && secondsEl) { + hoursEl.value = pad(hours); + minutesEl.value = pad(minutes); + secondsEl.value = pad(seconds); + } else { + console.warn("Timer input elements not found"); + } } function countTime() { - elapsedSecs++; + elapsedSecs = getElapsedSeconds(); displayTime(); } @@ -48,7 +55,8 @@ localStorage.setItem(getLocalStorageKey("startTime"), Date.now().toString()); } timerInterval = setInterval(countTime, 1000); - document.getElementById("startStopTimer").innerHTML = ""; + let btn = document.getElementById("startStopTimer"); + if (btn) btn.innerHTML = ""; localStorage.setItem("ticket-timer-running-" + ticketID, "true"); } @@ -60,7 +68,8 @@ let currentElapsed = getElapsedSeconds(); localStorage.setItem(getLocalStorageKey("pausedTime"), currentElapsed.toString()); localStorage.removeItem(getLocalStorageKey("startTime")); - document.getElementById("startStopTimer").innerHTML = ""; + let btn = document.getElementById("startStopTimer"); + if (btn) btn.innerHTML = ""; localStorage.setItem("ticket-timer-running-" + ticketID, "false"); } @@ -77,7 +86,8 @@ elapsedSecs = 0; clearTimeStorage(); displayTime(); - document.getElementById("startStopTimer").innerHTML = ""; + let btn = document.getElementById("startStopTimer"); + if (btn) btn.innerHTML = ""; } localStorage.setItem("ticket-timer-running-" + ticketID, "false"); } @@ -88,7 +98,8 @@ elapsedSecs = 0; clearTimeStorage(); displayTime(); - document.getElementById("startStopTimer").innerHTML = ""; + let btn = document.getElementById("startStopTimer"); + if (btn) btn.innerHTML = ""; } function handleInputFocus() { @@ -96,9 +107,9 @@ } function updateTimeFromInput() { - const hours = parseInt(document.getElementById("hours").value, 10) || 0; - const minutes = parseInt(document.getElementById("minutes").value, 10) || 0; - const seconds = parseInt(document.getElementById("seconds").value, 10) || 0; + const hours = parseInt(document.getElementById("hours")?.value, 10) || 0; + const minutes = parseInt(document.getElementById("minutes")?.value, 10) || 0; + const seconds = parseInt(document.getElementById("seconds")?.value, 10) || 0; elapsedSecs = (hours * 3600) + (minutes * 60) + seconds; if (!timerInterval) { @@ -111,61 +122,93 @@ } function checkStatusAndPauseTimer() { - var status = document.querySelector('select[name="status"]').value; - if (status.includes("Pending") || status.includes("Close")) { - pauseTimer(); + var statusEl = document.querySelector('select[name="status"]'); + if (statusEl) { + var status = statusEl.value; + if (status.includes("Pending") || status.includes("Close")) { + pauseTimer(); + } } } - // Attach input listeners - document.getElementById("hours").addEventListener('change', updateTimeFromInput); - document.getElementById("minutes").addEventListener('change', updateTimeFromInput); - document.getElementById("seconds").addEventListener('change', updateTimeFromInput); - - document.getElementById("hours").addEventListener('focus', handleInputFocus); - document.getElementById("minutes").addEventListener('focus', handleInputFocus); - document.getElementById("seconds").addEventListener('focus', handleInputFocus); - - document.querySelector('select[name="status"]').addEventListener('change', checkStatusAndPauseTimer); - - document.getElementById("startStopTimer").addEventListener('click', function() { - if (timerInterval === null) { - startTimer(); - } else { - pauseTimer(); + // Update on tab visibility change to handle background sleep + document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + elapsedSecs = getElapsedSeconds(); + displayTime(); } }); - document.getElementById("resetTimer").addEventListener('click', function() { - resetTimer(); - }); + // Attach input listeners with null checks + const hoursEl = document.getElementById("hours"); + if (hoursEl) { + hoursEl.addEventListener('change', updateTimeFromInput); + hoursEl.addEventListener('focus', handleInputFocus); + } - document.getElementById("ticket_add_reply").addEventListener('click', function() { - setTimeout(forceResetTimer, 100); - }); + const minutesEl = document.getElementById("minutes"); + if (minutesEl) { + minutesEl.addEventListener('change', updateTimeFromInput); + minutesEl.addEventListener('focus', handleInputFocus); + } - document.getElementById("ticket_close").addEventListener('click', function() { - setTimeout(clearTimeStorage, 100); - }); + const secondsEl = document.getElementById("seconds"); + if (secondsEl) { + secondsEl.addEventListener('change', updateTimeFromInput); + secondsEl.addEventListener('focus', handleInputFocus); + } + + const statusEl = document.querySelector('select[name="status"]'); + if (statusEl) { + statusEl.addEventListener('change', checkStatusAndPauseTimer); + } + + const startStopBtn = document.getElementById("startStopTimer"); + if (startStopBtn) { + startStopBtn.addEventListener('click', function() { + if (timerInterval === null) { + startTimer(); + } else { + pauseTimer(); + } + }); + } + + const resetBtn = document.getElementById("resetTimer"); + if (resetBtn) { + resetBtn.addEventListener('click', function() { + resetTimer(); + }); + } + + const addReplyBtn = document.getElementById("ticket_add_reply"); + if (addReplyBtn) { + addReplyBtn.addEventListener('click', function() { + setTimeout(forceResetTimer, 100); + }); + } + + const closeBtn = document.getElementById("ticket_close"); + if (closeBtn) { + closeBtn.addEventListener('click', function() { + setTimeout(clearTimeStorage, 100); + }); + } // Final initialization logic try { displayTime(); - // If no timer state, respect ticketAutoStart if (!localStorage.getItem(getLocalStorageKey("startTime")) && !localStorage.getItem(getLocalStorageKey("pausedTime"))) { - if (ticketAutoStart === 1) { + if (typeof ticketAutoStart !== "undefined" && ticketAutoStart === 1) { startTimer(); } else { pauseTimer(); } - } - // If timer already running, resume it - else if (localStorage.getItem(getLocalStorageKey("startTime"))) { + } else if (localStorage.getItem(getLocalStorageKey("startTime"))) { startTimer(); } - // Check and pause timer if status is pending checkStatusAndPauseTimer(); } catch (error) {