[UPDT] ATTENDANCE: Updated attendance app by replace activity delete method with hx attributes

This commit is contained in:
Horilla
2025-05-27 15:09:39 +05:30
parent 7f9faf17ff
commit 2cfbd10d22
3 changed files with 156 additions and 63 deletions

View File

@@ -124,6 +124,55 @@ function getCurrentLanguageCode(callback) {
}
}
function validateActivityIds(event) {
event.preventDefault();
getCurrentLanguageCode(function (languageCode) {
var textMessage = norowdeleteMessages[languageCode];
var $selectedActivity = $("#selectedActivity");
var idsRaw = $selectedActivity.attr("data-ids");
if (!idsRaw) {
Swal.fire({
text: textMessage,
icon: "warning",
confirmButtonText: "Close",
});
return;
}
let ids;
try {
ids = JSON.parse(idsRaw);
} catch (e) {
console.error("Invalid JSON in data-ids:", e);
Swal.fire({
text: "An unexpected error occurred. Please refresh the page.",
icon: "error",
confirmButtonText: "Close",
});
return;
}
if (!Array.isArray(ids) || ids.length === 0) {
Swal.fire({
text: textMessage,
icon: "warning",
confirmButtonText: "Close",
});
return;
}
$("#bulkDeleteIds").val(idsRaw);
// Submit the form programmatically
document.getElementById('bulkDeleteForm').dispatchEvent(
new Event('submit', { bubbles: true, cancelable: true })
);
});
}
$(".validate").change(function (e) {
var is_checked = $(this).is(":checked");
var closest = $(this)
@@ -1259,53 +1308,53 @@ $("#hourAccountbulkDelete").click(function (e) {
});
});
$("#attendanceActivityDelete").click(function (e) {
e.preventDefault();
var languageCode = null;
getCurrentLanguageCode(function (code) {
languageCode = code;
var confirmMessage = deleteMessages[languageCode];
var textMessage = norowdeleteMessages[languageCode];
ids = [];
ids.push($("#selectedActivity").attr("data-ids"));
ids = JSON.parse($("#selectedActivity").attr("data-ids"));
if (ids.length === 0) {
Swal.fire({
text: textMessage,
icon: "warning",
confirmButtonText: "Close",
});
} else {
Swal.fire({
text: confirmMessage,
icon: "error",
showCancelButton: true,
confirmButtonColor: "#008000",
cancelButtonColor: "#d33",
confirmButtonText: "Confirm",
}).then(function (result) {
if (result.isConfirmed) {
ids = [];
ids.push($("#selectedActivity").attr("data-ids"));
ids = JSON.parse($("#selectedActivity").attr("data-ids"));
$.ajax({
type: "POST",
url: "/attendance/attendance-activity-bulk-delete",
data: {
csrfmiddlewaretoken: getCookie("csrftoken"),
ids: JSON.stringify(ids),
},
success: function (response, textStatus, jqXHR) {
if (jqXHR.status === 200) {
location.reload();
}
},
});
}
});
}
});
});
// $("#attendanceActivityDelete").click(function (e) {
// e.preventDefault();
// var languageCode = null;
// getCurrentLanguageCode(function (code) {
// languageCode = code;
// var confirmMessage = deleteMessages[languageCode];
// var textMessage = norowdeleteMessages[languageCode];
// ids = [];
// ids.push($("#selectedActivity").attr("data-ids"));
// ids = JSON.parse($("#selectedActivity").attr("data-ids"));
// if (ids.length === 0) {
// Swal.fire({
// text: textMessage,
// icon: "warning",
// confirmButtonText: "Close",
// });
// } else {
// Swal.fire({
// text: confirmMessage,
// icon: "error",
// showCancelButton: true,
// confirmButtonColor: "#008000",
// cancelButtonColor: "#d33",
// confirmButtonText: "Confirm",
// }).then(function (result) {
// if (result.isConfirmed) {
// ids = [];
// ids.push($("#selectedActivity").attr("data-ids"));
// ids = JSON.parse($("#selectedActivity").attr("data-ids"));
// $.ajax({
// type: "POST",
// url: "/attendance/attendance-activity-bulk-delete",
// data: {
// csrfmiddlewaretoken: getCookie("csrftoken"),
// ids: JSON.stringify(ids),
// },
// success: function (response, textStatus, jqXHR) {
// if (jqXHR.status === 200) {
// location.reload();
// }
// },
// });
// }
// });
// }
// });
// });
$("#lateComeBulkDelete").click(function (e) {
e.preventDefault();

View File

@@ -61,7 +61,8 @@
</div>
</div>
{% if perms.attendance.change_attendancelatecomeearlyout or request.user|is_reportingmanager or perms.attendance.delete_attendancelatecomeearlyout %}
<div class="oh-dropdown ml-2" x-data="{open: false}" onclick="event.stopPropagation();event.preventDefault();">
<div class="oh-dropdown ml-2" x-data="{open: false}"
onclick="event.stopPropagation();event.preventDefault();">
<button class="oh-btn oh-btn--dropdown" @click="open = !open" @click.outside="open = false">
{% trans "Actions" %}
</button>
@@ -71,20 +72,21 @@
<li class="oh-dropdown__item">
<a href="#" class="oh-dropdown__link" id="activityInfoImport"
data-toggle="oh-modal-toggle" data-target="#objectCreateModal"
hx-get="{% url 'attendance-activity-import' %}" hx-target="#objectCreateModalTarget"
>
hx-get="{% url 'attendance-activity-import' %}"
hx-target="#objectCreateModalTarget">
{% trans "Import" %}
</a>
</li>
<li class="oh-dropdown__item">
<a href="#" class="oh-dropdown__link" id="activityInfoExport" data-toggle="oh-modal-toggle"
data-target="#objectUpdateModal" hx-get="{% url 'attendance-activity-info-export' %}"
<a href="#" class="oh-dropdown__link" id="activityInfoExport"
data-toggle="oh-modal-toggle" data-target="#objectUpdateModal"
hx-get="{% url 'attendance-activity-info-export' %}"
hx-target="#objectUpdateModalTarget">{% trans "Export" %}</a>
</li>
{% endif %}
{% if perms.attendance.delete_attendanceactivity %}
<li class="oh-dropdown__item">
<a href="#" id="attendanceActivityDelete" data-action="delete"
<a href="#" data-action="delete" onclick="validateActivityIds(event)"
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
</li>
{% endif %}
@@ -107,3 +109,11 @@
})
</script>
</section>
<form id="bulkDeleteForm" hx-post="{% url 'attendance-activity-bulk-delete' %}" hx-trigger="submit"
hx-confirm="{% trans 'Do you really want to delete all the selected activities?' %}"
hx-on-htmx-after-request="$('#unselectAllActivity').click(); $('#bulkDeleteIds').val('');"
hx-target="#activity-table" hx-swap="afterend">
{% csrf_token %}
<input type="hidden" name="ids" id="bulkDeleteIds" value="">
</form>

View File

@@ -879,22 +879,56 @@ def attendance_activity_delete(request, obj_id):
@require_http_methods(["POST"])
def attendance_activity_bulk_delete(request):
"""
This method is used to delete bulk of attendances
Deletes a bulk of AttendanceActivity records based on a list of IDs.
"""
ids = request.POST["ids"]
ids = json.loads(ids)
for attendance_id in ids:
try:
ids_json = request.POST.get("ids", "[]")
try:
activity = AttendanceActivity.objects.get(id=attendance_id)
activity.delete()
ids = json.loads(ids_json)
except json.JSONDecodeError:
messages.error(request, _("Invalid list of IDs provided."))
return HttpResponse("<script>$('.filterButton')[0].click()</script>")
try:
ids = [int(i) for i in ids]
except (ValueError, TypeError):
messages.error(request, _("Invalid list of IDs provided."))
return HttpResponse("<script>$('.filterButton')[0].click()</script>")
if not ids:
messages.warning(
request, _("No attendance activities selected for deletion.")
)
return HttpResponse("<script>$('.filterButton')[0].click()</script>")
# Perform the delete operation in a transaction
with transaction.atomic():
activities = AttendanceActivity.objects.filter(id__in=ids)
count = activities.count()
activities.delete()
if count > 0:
messages.success(
request,
_("{employee} activity deleted.").format(employee=activity.employee_id),
_("{count} attendance activities deleted successfully.").format(
count=count
),
)
else:
messages.info(
request,
_("No matching attendance activities were found to delete."),
)
except (AttendanceActivity.DoesNotExist, OverflowError, ValueError):
messages.error(request, _("Attendance not found."))
return JsonResponse({"message": "Success"})
except Exception as e:
logger.exception("Error during bulk delete of attendance activities")
messages.error(
request,
_("Failed to delete attendance activities: {error}").format(error=str(e)),
)
return HttpResponse("<script>$('.filterButton')[0].click()</script>")
def process_activity_dicts(activity_dicts):