[UPDT] EMPLOYEE: Updated disciplinary action crud operation to htmx

This commit is contained in:
Horilla
2024-02-26 20:10:10 +05:30
parent 99a810ec77
commit c580dc6a0f
7 changed files with 245 additions and 171 deletions

View File

@@ -771,8 +771,8 @@ class DisciplinaryAction(models.Model):
Disciplinary model
"""
choices = [("days", "Days"), ("hours", "Hours")]
employee_id = models.ManyToManyField(Employee, verbose_name="Employee")
choices = [("days", _("Days")), ("hours", _("Hours"))]
employee_id = models.ManyToManyField(Employee, verbose_name=_("Employees"))
action = models.ForeignKey(Actiontype, on_delete=models.CASCADE)
description = models.TextField(max_length=255)
unit_in = models.CharField(max_length=10, choices=choices, default="days")

View File

@@ -4,7 +4,6 @@ policies.py
This module is used to write operation related to policies
"""
import json
from django.contrib import messages
from django.http import HttpResponse, JsonResponse
@@ -22,7 +21,6 @@ from base.methods import (
)
@login_required
def view_policies(request):
"""
@@ -91,6 +89,7 @@ def view_policy(request):
},
)
@login_required
@permission_required("employee.delete_policy")
def delete_policies(request):
@@ -99,9 +98,10 @@ def delete_policies(request):
"""
ids = request.GET.getlist("ids")
Policy.objects.filter(id__in=ids).delete()
messages.success(request,"Policies deleted")
messages.success(request, "Policies deleted")
return redirect(view_policies)
@login_required
@permission_required("employee.change_policy")
def add_attachment(request):
@@ -155,14 +155,16 @@ def disciplinary_actions(request):
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
previous_data = request.GET.urlencode()
return render(request,
"disciplinary_actions/disciplinary_nav.html",
{
"data": page_obj,
"pd": previous_data,
"f": form,
})
return render(
request,
"disciplinary_actions/disciplinary_nav.html",
{
"data": page_obj,
"pd": previous_data,
"f": form,
},
)
@login_required
@@ -171,16 +173,16 @@ def create_actions(request):
"""
Method is used to create Disciplinaryaction
"""
form = DisciplinaryActionForm(initial=request.GET)
form = DisciplinaryActionForm()
employees = []
if request.method == "POST":
form = DisciplinaryActionForm(request.POST, request.FILES)
if form.is_valid():
emp = form.cleaned_data['employee_id']
employee_ids = form.cleaned_data["employee_id"]
for i in emp:
name = i.employee_user_id
employees.append(name)
for employee in employee_ids:
user = employee.employee_user_id
employees.append(user)
form.save()
messages.success(request, _("Disciplinary action taken."))
notify.send(
@@ -195,13 +197,12 @@ def create_actions(request):
icon="chatbox-ellipses",
)
return HttpResponse("<script>window.location.reload()</script>")
return render(request, "disciplinary_actions/form.html", {"form": form})
@login_required
@permission_required("employee.change_disciplinaryaction")
def update_actions(request, action_id ):
def update_actions(request, action_id):
"""
Method is used to update Disciplinaryaction
"""
@@ -211,9 +212,9 @@ def update_actions(request, action_id ):
employees = []
if request.method == "POST":
form = DisciplinaryActionForm(request.POST, request.FILES, instance=action)
if form.is_valid():
emp = form.cleaned_data['employee_id']
emp = form.cleaned_data["employee_id"]
for i in emp:
name = i.employee_user_id
@@ -233,8 +234,6 @@ def update_actions(request, action_id ):
redirect="/employee/disciplinary-actions/",
icon="chatbox-ellipses",
)
return HttpResponse("<script>window.location.reload()</script>")
return render(request, "disciplinary_actions/update_form.html", {"form": form})
@@ -245,9 +244,9 @@ def delete_actions(request, action_id):
This method is used to delete Disciplinary action
"""
DisciplinaryAction.objects.filter(id = action_id).delete()
DisciplinaryAction.objects.filter(id=action_id).delete()
messages.success(request, _("Disciplinary action deleted."))
return redirect(disciplinary_actions)
return redirect(disciplinary_filter_view)
@login_required
@@ -269,7 +268,7 @@ def disciplinary_filter_view(request):
previous_data = request.GET.urlencode()
dis_filter = DisciplinaryActionFilter(request.GET).qs
page_number = request.GET.get("page")
page_number = request.GET.get("page")
page_obj = paginator_qry(dis_filter, page_number)
data_dict = parse_qs(previous_data)
get_key_instances(DisciplinaryAction, data_dict)

View File

@@ -8,7 +8,7 @@
</div>
<form
hx-get="{% url 'disciplinary-filter-view' %}"
hx-target="#policyContainer"
hx-target="#actionContainer"
id="filterForm"
class="d-flex"
onsubmit = "event.preventDefault()"
@@ -119,7 +119,7 @@
</div>
</div>
<div class="oh-main__titlebar-button-container">
<a hx-get="{% url 'create-actions' %}" hx-target="#createannouncementForm" data-toggle="oh-modal-toggle" data-target="#anouncementModal" class="oh-btn oh-btn--secondary">
<a hx-get="{% url 'create-actions' %}" hx-target="#actionCreateForm" data-toggle="oh-modal-toggle" data-target="#actionCreateModal" class="oh-btn oh-btn--secondary">
<ion-icon name="add-outline"></ion-icon>
{% trans 'Take An Action' %}
</a>
@@ -136,7 +136,7 @@
hx-get="{% url 'action-type-create' %}?dynamic=employee" hx-target="#dynamicCreateModalBody">
</span>
{% if data %}
<div class="oh-wrapper" id="policyContainer">
<div class="oh-wrapper" id="actionContainer">
{% include 'disciplinary_actions/disciplinary_records.html' %}
</div>
{% else %}
@@ -196,47 +196,21 @@
<!-- start of create modal -->
<div
class="oh-modal"
id="anouncementModal"
id="actionCreateModal"
role="dialog"
aria-labelledby="emptagModal"
aria-hidden="true"
>
<div class="oh-modal__dialog">
<div class="oh-modal__dialog-header">
<h2 class="oh-modal__dialog-title" id="createModalTitle">
{% trans "Take An Action." %}
</h2>
<button class="oh-modal__close" aria-label="Close">
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body" id="createannouncementForm"></div>
</div>
>
<div class="oh-modal__dialog" id="actionCreateForm"> </div>
</div>
<!-- end of create modal -->
<!-- start of update modal -->
<div
class="oh-modal"
id="announcementUpdateModal"
role="dialog"
aria-labelledby="announcementUpdateModal"
aria-hidden="true"
>
<div class="oh-modal__dialog">
<div class="oh-modal__dialog-header">
<h5 class="oh-modal__dialog-title" id="announcementUpdateModalLabel"
>{% trans "Edit Action." %}</span
>
<button class="oh-modal__close" aria-label="Close" >
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body" id='announcementUpdate'>
</div>
</div>
<div class="oh-modal" id="actionUpdateModal"
role="dialog" aria-labelledby="actionUpdateModal"
aria-hidden="true">
<div class="oh-modal__dialog" id='actionUpdateForm'> </div>
</div>
<!-- end of update modal -->

View File

@@ -4,7 +4,17 @@
{% load static %}
{% load i18n %}
{% include 'filter_tags.html' %}
{% if messages %}
<div class="oh-wrapper">
{% for message in messages %}
<div class="oh-alert-container">
<div class="oh-alert oh-alert--animated {{message.tags}}">
{{ message }}
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% if data %}
<!-- start of column toggle -->
<div class="oh-table_sticky--wrapper">
@@ -39,75 +49,105 @@
</div>
</div>
<div class="oh-sticky-table__tbody">
{% for i in data %}
<div class="oh-sticky-table__tr">
<div class="oh-sticky-table__td">
{% for emp in i.employee_id.all %}
<div class="oh-profile oh-profile--md mt-2">
<div class="oh-profile__avatar mr-1">
<img src="{{ emp.get_avatar }}" class="oh-profile__image" alt="{{ emp }}">
</div>
<span class="oh-profile__name oh-text--dark">{{ emp }}</span>
</div><br>
{% endfor %}
{% for i in data %}
<div class="oh-sticky-table__tr oh-permission-table__tr oh-permission-table--collapsed">
<div class="oh-sticky-table__sd oh-permission-table--toggle" data-toggle-count>
<div class="d-flex align-items-center">
<button class="oh-permission-table__collapse me-2">
<span title="{% trans "Reveal" %}"><ion-icon class="oh-permission-table__collapse-down" name="chevron-down-outline"></ion-icon></span>
<span title="{% trans "Collapse" %}"><ion-icon class="oh-permission-table__collapse-up" name="chevron-up-outline"></ion-icon></span>
</button>
<span class="count-span" style="font-style:italic;color:hsl(0deg,0%,37%);">{{i.employee_id.all|length}}
{% if i.employee_id.all|length > 1 %}
{% trans "Employees" %}
{% else %}
{% trans "Employee" %}
{% endif %}
</span>
</div>
{% for emp in i.employee_id.all %}
<span class="oh-user-panel oh-collapse-panel" data-type="user">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img
src="https://ui-avatars.com/api/?name={{emp.get_full_name}}&background=random"
class="oh-profile__image"
alt="Baby C."
/>
</div>
{% if i.action.action_type == 'suspension' %}
<div data-cell-index="1" class="oh-sticky-table__td">{{ i.action }}
<p class="fw-bold mt-2">{% trans "Suspended for" %}
{% if i.unit_in == "days" %}
{{ i.days }} {% trans "days" %}.
{% else %}
{{ i.hours }} {% trans "hours" %}.
{% endif %}
</p>
</div>
{% else %}
<div data-cell-index="1" class="oh-sticky-table__td">{{ i.action }}</div>
{% endif %}
{% if i.action.action_type == 'suspension' and i.unit_in == "days" %}
<div data-cell-index="2" class="oh-sticky-table__td">
<span class="dateformat_changer">{{ i.start_date }}</span>
&nbsp to &nbsp<span class="dateformat_changer">{{ i.start_date | add_days:i.days }}</span>
<span class="oh-profile__name oh-text--dark" title="{{emp}}"
>{{emp.employee_first_name|truncatechars:8}}</span
>
</div>
<a title="{% trans "Remove" %}" hx-target="#recruitment-container"class="oh-user-panel__remove">
<ion-icon name="close-outline"></ion-icon>
</a>
</span>
{% endfor %}
</div>
{% if i.action.action_type == 'suspension' %}
<div data-cell-index="1" class="oh-sticky-table__td">{{ i.action }}
<p class="fw-bold mt-2">{% trans "Suspended for" %}
{% if i.unit_in == "days" %}
{{ i.days }} {% trans "days" %}.
{% else %}
{{ i.hours }} {% trans "hours" %}.
{% endif %}
</p>
</div>
{% else %}
<div data-cell-index="1" class="oh-sticky-table__td">{{ i.action }}</div>
{% endif %}
{% if i.action.action_type == 'suspension' and i.unit_in == "days" %}
<div data-cell-index="2" class="oh-sticky-table__td">
<span class="dateformat_changer">{{ i.start_date }}</span>
&nbsp to &nbsp<span class="dateformat_changer">{{ i.start_date | add_days:i.days }}</span>
</div>
{% else %}
<div data-cell-index="2" class="oh-sticky-table__td dateformat_changer">{{ i.start_date }}</div>
{% endif %}
{% if i.attachment %}
<div data-cell-index="3" class="oh-sticky-table__td">
<div class="oh-helpdesk_attached--content">
<div class="oh-helpdesk__attachment-icon">
<a href="{{ i.attachment.url }}" target="_blank"><span class="oh-file-icon oh-file-icon--pdf"></span></a>
</div>
{% else %}
<div data-cell-index="2" class="oh-sticky-table__td dateformat_changer">{{ i.start_date }}</div>
{% endif %}
{% if i.attachment %}
<div data-cell-index="3" class="oh-sticky-table__td">
<div class="oh-helpdesk_attached--content">
<div class="oh-helpdesk__attachment-icon">
<a href="{{ i.attachment.url }}" target="_blank"><span class="oh-file-icon oh-file-icon--pdf"></span></a>
</div>
<a href="{{ i.attachment.url }}" target="_blank"><span class="oh-helpdesk__filename">{% trans "View File" %}</span></a>
</div>
</div>
{% else %}
<div data-cell-index="3" class="oh-sticky-table__td">{% trans "No file has been uploaded." %}</div>
{% endif %}
<div data-cell-index="4" class="oh-sticky-table__td">{{ i.description|truncatechars:25}}</div>
{% if perms.payroll.change_disciplinaryaction or perms.payroll.delete_disciplinaryaction %}
<div class="oh-sticky-table__td">
<div class="oh-btn-group" >
{% if perms.payroll.change_disciplinaryaction %}
<a hx-get="{% url 'update-actions' i.id %}" hx-target='#announcementUpdate' data-toggle='oh-modal-toggle' data-target="#announcementUpdateModal" class="oh-btn oh-btn--light-bkg w-50" title="{% trans 'Edit' %}">
<ion-icon name="create-outline"></ion-icon></a>
{% endif %}
{% if perms.payroll.delete_disciplinaryaction %}
<form action="{% url 'delete-actions' i.id %}" onsubmit="return confirm('{% trans "Are you sure you want to delete this disciplinary action?" %}');" method='post' class="w-50">
{% csrf_token %}
<button type='submit' class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100" title="{% trans 'Remove' %}"><ion-icon name="trash-outline"></ion-icon></button>
</form>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
<a href="{{ i.attachment.url }}" target="_blank"><span class="oh-helpdesk__filename">{% trans "View File" %}</span></a>
</div>
</div>
{% else %}
<div data-cell-index="3" class="oh-sticky-table__td">{% trans "No file has been uploaded." %}</div>
{% endif %}
<div data-cell-index="4" class="oh-sticky-table__td">{{ i.description|truncatechars:25}}</div>
{% if perms.payroll.change_disciplinaryaction or perms.payroll.delete_disciplinaryaction %}
<div class="oh-sticky-table__td">
<div class="oh-btn-group" >
{% if perms.payroll.change_disciplinaryaction %}
<a hx-get="{% url 'update-actions' i.id %}" hx-target='#actionUpdateForm' data-toggle='oh-modal-toggle' data-target="#actionUpdateModal" class="oh-btn oh-btn--light-bkg w-50" title="{% trans 'Edit' %}">
<ion-icon name="create-outline"></ion-icon></a>
{% endif %}
{% if perms.payroll.add_disciplinaryaction %}
<a class="oh-btn oh-btn--light-bkg w-50" data-toggle="oh-modal-toggle"
data-target="#actionCreateModal" hx-get="{% url 'duplicate-disciplinary-actions' i.id %}?{{pg}}"
title="{% trans 'Duplicate' %}" hx-target="#actionCreateForm"
style= "cursor: pointer;"
>
<ion-icon name="copy-outline"></ion-icon>
</a>
{% endif %}
{% if perms.payroll.delete_disciplinaryaction %}
<form hx-confirm="{% trans "Are you sure you want to delete this disciplinary action?" %}" hx-post="{% url 'delete-actions' i.id %}" hx-target="#actionContainer" class="w-50">
{% csrf_token %}
<button type='submit' class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100" title="{% trans 'Remove' %}"><ion-icon name="trash-outline"></ion-icon></button>
</form>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
@@ -247,4 +287,11 @@
$("#displinaryActionCells").find("[type=checkbox]").prop("checked",true)
}
$("[type=checkbox]").change()
$(document).ready(function () {
$("[data-toggle-count]").click(function (e) {
e.preventDefault();
span = $(this).parent().find(".count-span").toggle()
});
});
</script>

View File

@@ -10,22 +10,34 @@
</div>
<script>
setTimeout(function () {
$(".oh-modal__close--custom").click();
$(".oh-modal__close").click();
}, 1000);
</script>
{% endif %}
<form
hx-post="{% url 'create-actions' %}"
hx-target="#createannouncementForm"
method="post"
hx-encoding="multipart/form-data"
id="disciplinaryActionForm"
>
{% csrf_token %}
{{form.as_p}}
</form>
<div class="oh-modal__dialog-header">
<h2 class="oh-modal__dialog-title" id="createModalTitle">
{% trans "Take An Action." %}
</h2>
<button
class="oh-modal__close"
aria-label="Close"
hx-get="{% url 'disciplinary-filter-view' %}"
hx-target="#actionContainer"
>
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body">
<form
hx-post="{% url 'create-actions' %}"
hx-target="#actionCreateForm"
method="post"
hx-encoding="multipart/form-data"
id="disciplinaryActionForm"
>
{% csrf_token %} {{form.as_p}}
</form>
</div>
<script>
$(document).ready(function () {
var actionElement = $("#id_action");
@@ -36,8 +48,8 @@
}
}
});
$('#id_days').parent().hide();
$('#id_unit_in').parent().hide();
$('#id_hours').parent().hide();
$('[name=days]').prop('required', false);
$("#id_days").parent().hide();
$("#id_unit_in").parent().hide();
$("#id_hours").parent().hide();
$("[name=days]").prop("required", false);
</script>

View File

@@ -1,25 +1,52 @@
{% load i18n %}
{% if form.errors %}
<!-- form errors -->
<div class="oh-wrapper">
<div class="oh-alert-container">
{% for error in form.non_field_errors %}
<div class="oh-alert oh-alert--animated oh-alert--danger">
{{ error }}
</div>
{% endfor %}
</div>
{% load i18n %} {% if messages %}
<div class="oh-wrapper">
{% for message in messages %}
<div class="oh-alert-container">
<div class="oh-alert oh-alert--animated {{message.tags}}">
{{ message }}
</div>
</div>
{% endfor %}
</div>
<script>
setTimeout(function () {
$(".oh-modal__close").click();
}, 1000);
</script>
{% endif %} {% if form.errors %}
<!-- form errors -->
<div class="oh-wrapper">
<div class="oh-alert-container">
{% for error in form.non_field_errors %}
<div class="oh-alert oh-alert--animated oh-alert--danger">{{ error }}</div>
{% endfor %}
</div>
</div>
{% endif %}
<form
<div class="oh-modal__dialog-header">
<h5 class="oh-modal__dialog-title" id="actionUpdateModalLabel">
{% trans "Edit Action." %}
</h5>
<button
class="oh-modal__close"
aria-label="Close"
hx-get="{% url 'disciplinary-filter-view' %}"
hx-target="#actionContainer"
>
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body">
<form
hx-post="{% url 'update-actions' form.instance.id %}"
hx-target="#announcementUpdate"
method="post"
hx-encoding="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
</form>
hx-target="#actionUpdateForm"
method="post"
hx-encoding="multipart/form-data"
>
{% csrf_token %} {{form.as_p}}
</form>
</div>
<script>
$("#announcementUpdate #id_action").change()
</script>
$("#actionUpdateForm #id_action").change();
</script>

View File

@@ -5,9 +5,10 @@ This module is used to map url path with view methods.
"""
from django.urls import path
from base.views import object_delete
from base.views import object_delete, object_duplicate
from employee import not_in_out_dashboard, policies, views
from employee.models import Employee
from employee.forms import DisciplinaryActionForm
from employee.models import DisciplinaryAction, Employee
from horilla_documents.models import DocumentRequest
urlpatterns = [
@@ -123,7 +124,11 @@ urlpatterns = [
views.employee_archive,
name="employee-archive",
),
path("replace-employee/<int:emp_id>/",views.replace_employee,name="replace-employee"),
path(
"replace-employee/<int:emp_id>/",
views.replace_employee,
name="replace-employee",
),
path(
"employee-user-group-assign-delete/<int:obj_id>/",
views.employee_user_group_assign_delete,
@@ -325,6 +330,16 @@ urlpatterns = [
policies.disciplinary_actions,
name="disciplinary-actions",
),
path(
"duplicate-disciplinary-actions/<int:obj_id>/",
object_duplicate,
name="duplicate-disciplinary-actions",
kwargs={
"model": DisciplinaryAction,
"form": DisciplinaryActionForm,
"template": "disciplinary_actions/form.html",
},
),
path("create-actions", policies.create_actions, name="create-actions"),
path(
"update-actions/<int:action_id>/",