[FIX] ATTENDANCE: Fixed time runner not running for the first check-in

This commit is contained in:
Horilla
2025-08-18 12:44:06 +05:30
parent e09bb49877
commit 868de7910f
11 changed files with 55 additions and 164 deletions

View File

@@ -4,4 +4,4 @@
<div class="" data-target="#penaltyViewModal" data-toggle="oh-modal-toggle" hx-get="{% url "view-penalties" %}?late_early_id={{instance.id}}" hx-target="#penaltyViewModalBody" align="center" style="background-color: rgba(229, 79, 56, 0.036); border: 2px solid rgb(229, 79, 56); border-radius: 18px; padding: 10px; font-weight: bold; width: 150px;" onclick="event.stopPropagation();">Penalties :{{instance.get_penalties_count}}</div>
{% else %}
<div class="" style="background-color: rgba(144, 238, 144, 0.036); border: 2px solid rgb(144, 238, 144); border-radius: 18px; padding: 10px; width: 150px;" align="center">No Penalties</div>
{% endif %}
{% endif %}

View File

@@ -5,4 +5,4 @@
{% endfor %}
{% else %}
{% trans "Nil" %}
{% endif %}
{% endif %}

View File

@@ -7,6 +7,8 @@ This module is used register endpoints to the check-in check-out functionalities
import ipaddress
import logging
from django.shortcuts import render
logger = logging.getLogger(__name__)
from datetime import date, datetime, timedelta
@@ -292,50 +294,8 @@ def clock_in(request):
end_time=end_time_sec,
in_datetime=datetime_now,
)
script = ""
hidden_label = ""
time_runner_enabled = timerunner_enabled(request)["enabled_timerunner"]
mouse_in = ""
mouse_out = ""
if time_runner_enabled:
script = """
<script>
$(".time-runner").removeClass("stop-runner");
run = 1;
at_work_seconds = {at_work_seconds_forecasted};
</script>
""".format(
at_work_seconds_forecasted=employee.get_forecasted_at_work()[
"forecasted_at_work_seconds"
]
)
hidden_label = """
style="display:none"
"""
mouse_in = """ onmouseenter = "$(this).find('span').show();$(this).find('.time-runner').hide();" """
mouse_out = """ onmouseleave = "$(this).find('span').hide();$(this).find('.time-runner').show();" """
return HttpResponse(
"""
<button class="oh-btn oh-btn--warning-outline check-in mr-2"
{mouse_in}
{mouse_out}
hx-get="/attendance/clock-out"
hx-target='#attendance-activity-container'
hx-swap='innerHTML'><ion-icon class="oh-navbar__clock-icon mr-2
text-warning"
name="exit-outline"></ion-icon>
<span {hidden_label} class="hr-check-in-out-text">{check_out}</span>
<div class="time-runner"></div>
</button>
{script}
""".format(
check_out=_("Check-Out"),
script=script,
hidden_label=hidden_label,
mouse_in=mouse_in,
mouse_out=mouse_out,
)
return render(
request, "attendance/components/in_out_component.html", {"run": 1}
)
return HttpResponse(
_(
@@ -549,52 +509,10 @@ def clock_out(request):
shift=shift,
)
script = ""
hidden_label = ""
time_runner_enabled = timerunner_enabled(request)["enabled_timerunner"]
mouse_in = ""
mouse_out = ""
if time_runner_enabled:
script = """
<script>
$(document).ready(function () {{
$('.at-work-seconds').html(secondsToDuration({at_work_seconds_forecasted}))
}});
run = 0;
at_work_seconds = {at_work_seconds_forecasted};
</script>
""".format(
at_work_seconds_forecasted=employee.get_forecasted_at_work()[
"forecasted_at_work_seconds"
],
)
hidden_label = """
style="display:none"
"""
mouse_in = """ onmouseenter="$(this).find('div.at-work-seconds').hide();$(this).find('span').show();" """
mouse_out = """onmouseleave="$(this).find('div.at-work-seconds').show();$(this).find('span').hide();" """
return HttpResponse(
"""
<button class="oh-btn oh-btn--success-outline mr-2"
{mouse_in}
{mouse_out}
hx-get="/attendance/clock-in"
hx-target='#attendance-activity-container'
hx-swap='innerHTML'>
<ion-icon class="oh-navbar__clock-icon mr-2 text-success"
name="enter-outline"></ion-icon>
<span class="hr-check-in-out-text" {hidden_label} >{check_in}</span>
<div class="at-work-seconds"></div>
</button>
{script}
""".format(
check_in=_("Check-In"),
script=script,
hidden_label=hidden_label,
mouse_in=mouse_in,
mouse_out=mouse_out,
)
return render(
request, "attendance/components/in_out_component.html", {"run": 1}
)
else:
messages.error(request, _("Check in/Check out feature is not enabled."))
return HttpResponse("<script>location.reload();</script>")

View File

@@ -4,6 +4,9 @@ var whiteLabelCompany = $("#whiteLabelCompany").data("company");
// time-runner
function secondsToDuration(seconds) {
if (seconds < 0){
seconds = 0
}
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor((seconds % 3600) / 60);
var remainingSeconds = Math.floor(seconds % 60);

View File

@@ -7,11 +7,11 @@
{% if request.user|is_clocked_in and get_forecasted_at_work.has_attendance %}
<button class="check checkout" hx-get="{% url 'clock-out' %}" hx-target='#attendance-activity-container' hx-swap='innerHTML'>
<span class="date">
<i class="fa-solid fa-right-from-bracket pe-2"></i> {% if get_forecasted_at_work.has_attendance %} <div class="time-runner"></div> {% endif %}
<i class="fa-solid fa-right-from-bracket pe-2"></i><div class="time-runner"></div>
</span>
<span class="con hr-Check-In-out-text">{% trans "Check Out" %}</span>
</button>
<span class="at_work_seconds" data-at-work-seconds = "{{ request.user.employee_get.get_forecasted_at_work.forecasted_at_work_seconds }}" data-run= "{{run|default:1}}" ></span>
<span class="at_work_seconds" data-at-work-seconds = "{{ get_forecasted_at_work.forecasted_at_work_seconds|default:0 }}" data-run= "{{run|default:1}}" ></span>
{% else %}
<button class="check checkin" hx-get="{% url 'clock-in' %}" hx-target='#attendance-activity-container' hx-swap='innerHTML'>
@@ -20,11 +20,11 @@
</span>
<span class="con">{% trans "Check In" %}</span>
</button>
<span class="at_work_seconds" data-at-work-seconds = "{{ request.user.employee_get.get_forecasted_at_work.forecasted_at_work_seconds }}" data-run= "{{run|default:0}}" ></span>
<span class="at_work_seconds" data-at-work-seconds = "{{ get_forecasted_at_work.forecasted_at_work_seconds|default:0 }}" data-run= "{{run|default:0}}" ></span>
{% if enabled_timerunner %}
<script>
$(document).ready(function () {
$('.at-work-seconds').html(secondsToDuration({{get_forecasted_at_work.forecasted_at_work_seconds}}))
$('.at-work-seconds').html(secondsToDuration({{get_forecasted_at_work.forecasted_at_work_seconds}}))
});
run = 0
</script>
@@ -36,66 +36,39 @@
{% endwith %}
{% endif %}
<script>
var at_work_seconds = $(".at_work_seconds").data("at-work-seconds");
var run = $(".at_work_seconds").data("run");
var whiteLabelCompany = $("#whiteLabelCompany").data("company");
{% comment %} <script>
var at_work_seconds = {{ request.user.employee_get.get_forecasted_at_work.forecasted_at_work_seconds }}
var run = {{run|default:0}};
// time-runner
function secondsToDuration(seconds) {
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor((seconds % 3600) / 60);
var remainingSeconds = Math.floor(seconds % 60);
// add leading zeros if necessary
var formattedHours = (hours < 10) ? "0" + hours : hours;
var formattedMinutes = (minutes < 10) ? "0" + minutes : minutes;
var formattedSeconds = (remainingSeconds < 10) ? "0" + remainingSeconds : remainingSeconds;
return formattedHours + ":" + formattedMinutes + ":" + formattedSeconds;
}
// accessing initial worked hours from the user
$(".time-runner").not("title").html(secondsToDuration(at_work_seconds));
$("title.time-runner").html("{{white_label_company_name}} | " + secondsToDuration(at_work_seconds));
setInterval(() => {
if (run) {
at_work_seconds = parseInt(at_work_seconds) + 1
$("div.time-runner").html(secondsToDuration(at_work_seconds));
$("title").html("{{white_label_company_name}} | " + secondsToDuration(at_work_seconds));
}
}, 1000);
function switchTab(e) {
let parentContainerEl = e.target.closest(".oh-tabs");
let tabElement = e.target.closest(".oh-tabs__tab");
let targetSelector = e.target.dataset.target;
let targetEl = parentContainerEl
? parentContainerEl.querySelector(targetSelector)
: null;
// Highlight active tabs
if (tabElement && !tabElement.classList.contains("oh-tabs__tab--active")) {
parentContainerEl
.querySelectorAll(".oh-tabs__tab--active")
.forEach(function (item) {
item.classList.remove("oh-tabs__tab--active");
});
if (!tabElement.classList.contains("oh-tabs__new-tab")) {
tabElement.classList.add("oh-tabs__tab--active");
// time-runner
function secondsToDuration(seconds) {
if (seconds < 0){
seconds = 0
}
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor((seconds % 3600) / 60);
var remainingSeconds = Math.floor(seconds % 60);
var formattedHours = (hours < 10) ? "0" + hours : hours;
var formattedMinutes = (minutes < 10) ? "0" + minutes : minutes;
var formattedSeconds = (remainingSeconds < 10) ? "0" + remainingSeconds : remainingSeconds;
return formattedHours + ":" + formattedMinutes + ":" + formattedSeconds;
}
// Switch tabs
if (targetEl && !targetEl.classList.contains("oh-tabs__content--active")) {
parentContainerEl
.querySelectorAll(".oh-tabs__content--active")
.forEach(function (item) {
item.classList.remove("oh-tabs__content--active");
});
targetEl.classList.add("oh-tabs__content--active");
if (window.timeRunnerInterval) {
clearInterval(window.timeRunnerInterval);
}
}
</script> {% endcomment %}
$(".time-runner").not("title").html(secondsToDuration(at_work_seconds));
$("title.time-runner").html(` ${whiteLabelCompany} | ` + secondsToDuration(at_work_seconds));
if (run) {
window.timeRunnerInterval = setInterval(() => {
at_work_seconds = parseInt(at_work_seconds) + 1;
$("div.time-runner").html(secondsToDuration(at_work_seconds));
$("title").html(` ${whiteLabelCompany} | ` + secondsToDuration(at_work_seconds));
}, 1000);
}
</script>

View File

@@ -50,7 +50,7 @@
$("#sortable li").each(function (index) {
order.push($(this).data("id"));
});
$.ajax({
url: "{% url 'update-stage-sequence' offboarding.id %}",
method: "POST",

View File

@@ -30,7 +30,7 @@
{% endif %}
{% if perms.recruitment.delete_stage %}
<li class="oh-dropdown__item oh-dropdown__link--danger">
<a data-toggle="oh-modal-toggle"
data-target="#deleteConfirmation"
hx-get="{% url 'generic-delete' %}?model=recruitment.Stage&pk={{stage.pk}}"
@@ -38,16 +38,16 @@
</li>
{% endif %}
</ul>
</div>
</div>
</div>
<div
<div
class="oh-tabs__movable-body position-relative"
hx-get="{% url "candidate-lists-cbv" stage.pk stage.recruitment_id.pk %}?{{request.GET.urlencode}}"
hx-trigger="load"
></div>
</div>
</div>
@@ -62,4 +62,3 @@
badge.attr("title", title);
</script>
</div>

View File

@@ -42,11 +42,11 @@
</div>
</div>
</div>
<div
<div
class="oh-tabs__movable-body position-relative"
hx-get="{{url}}?{% for parameter in parameters %}{{parameter|format:group}}&{% endfor %}{{request.GET.urlencode}}"
hx-trigger="load"
>
</div>
</div>
@@ -62,4 +62,3 @@
badge.attr("title", title);
</script>
</div>

View File

@@ -32,11 +32,10 @@
<div id="attendance-activity-container">
{% include "attendance/components/in_out_component.html" %}
</div>
<script src="{% static 'horilla_theme/assets/js/timeRunner.js' %}"></script>
{% endif %}
{% endif %}
<button
class="hidden md:block p-2 group text-primary-600 w-12 h-12 bg-primary-100 hover:bg-primary-600 rounded-full transition duration-300 flex items-center justify-center"
class="md:block p-2 group text-primary-600 w-12 h-12 bg-primary-100 hover:bg-primary-600 rounded-full transition duration-300 flex items-center justify-center"
>
<a href="{% url 'general-settings' %}">
<i