[FIX] OFFBOARDING: Fixed the issues in Offboarding creation, stage creation and added pagination and style fixes

This commit is contained in:
Horilla
2024-12-05 14:45:39 +05:30
parent 109d2f055d
commit 8cb9331b51
4 changed files with 147 additions and 18 deletions

View File

@@ -32,9 +32,12 @@ class Offboarding(HorillaModel):
managers = models.ManyToManyField(Employee)
status = models.CharField(max_length=10, default="ongoing", choices=statuses)
company_id = models.ForeignKey(
Company, on_delete=models.CASCADE, null=True, editable=False
Company,
on_delete=models.CASCADE,
null=True,
verbose_name="Company",
)
objects = HorillaCompanyManager()
objects = HorillaCompanyManager("company_id")
def __str__(self):
return self.title

View File

@@ -132,6 +132,57 @@
{% endif %}
{% endfor %}
</div>
<div class="oh-wrapper mb-5">
<!-- Paginator Section -->
<div class="oh-pagination">
<span
class="oh-pagination__page"
data-toggle="modal"
data-target="#addEmployeeModal"
>
{% trans "Page" %} {{ paginated_offboardings.number }} {% trans "of" %} {{ paginated_offboardings.paginator.num_pages }}.
</span
>
<nav class="oh-pagination__nav">
<div class="oh-pagination__input-container me-3">
<span class="oh-pagination__label me-1">{% trans "Page" %}</span>
<input
type="number"
name="page"
class="oh-pagination__input"
value="{{paginated_offboardings.number}}"
hx-get="{% url 'offboarding-pipeline-filter' %}?{{pd}}" hx-target="#offboardingContainer"
min="1"
/>
<span class="oh-pagination__label">{% trans "of" %} {{paginated_offboardings.paginator.num_pages}}</span>
</div>
<ul class="oh-pagination__items">
{% if paginated_offboardings.has_previous %}
<li class="oh-pagination__item oh-pagination__item--wide">
<a href="{% url 'offboarding-pipeline' %}?{{pd}}&page=1" class="oh-pagination__link">{% trans "First" %}</a>
</li>
<li class="oh-pagination__item oh-pagination__item--wide">
<a href="{% url 'offboarding-pipeline' %}?{{pd}}&page={{ paginated_offboardings.previous_page_number }}" class="oh-pagination__link">{% trans "Previous" %}</a>
</li>
{% endif %}
{% if paginated_offboardings.has_next %}
<li class="oh-pagination__item oh-pagination__item--wide">
<a href="{% url 'offboarding-pipeline' %}?{{pd}}&page={{ paginated_offboardings.next_page_number }}" class="oh-pagination__link">{% trans "Next" %}</a>
</li>
<li class="oh-pagination__item oh-pagination__item--wide">
<a href="{% url 'offboarding-pipeline' %}?{{pd}}&page={{ paginated_offboardings.paginator.num_pages }}" class="oh-pagination__link">{% trans "Last" %}</a>
</li>
{% endif %}
</ul>
</nav>
</div>
</div>
{% else %}
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100%;">
<img style="display: block; width: 15%; margin: 20px auto; filter: opacity(0.5);" src="{% static 'images/ui/no-results.png' %}" class="" alt="Page not found. 404." />
@@ -142,14 +193,65 @@
</div>
<script>
let activeTab = localStorage.getItem("activeTabOffboarding")
if (activeTab) {
$(`.oh-tabs__tab[data-target="${activeTab}"]`).addClass("oh-tabs__tab--active")
$(`${activeTab}`).addClass("oh-tabs__content--active")
}
function myFunction(val) {
var selects = $("[data-selected-stage]").val(val)
selects.siblings('[type=submit]').click()
}
$(document).ready(function () {
// Function to apply the active tab
function applyActiveTab() {
// Retrieve the active tab from localStorage
let activeTab = localStorage.getItem("activeTabOffboarding");
// Check if the active tab exists in the current DOM
if (activeTab && $(`.oh-tabs__tab[data-target="${activeTab}"]`).length > 0) {
console.log("Active Tab exists. Activating it.");
// Remove active classes from all tabs and content
$(".oh-tabs__tab").removeClass("oh-tabs__tab--active fw-bold");
$(".oh-tabs__content").removeClass("oh-tabs__content--active fw-bold");
// Activate the saved tab and its content
$(`.oh-tabs__tab[data-target="${activeTab}"]`).addClass("oh-tabs__tab--active fw-bold");
$(`${activeTab}`).addClass("oh-tabs__content--active fw-bold");
} else {
console.log("Active Tab not found. Activating default tab.");
// Fallback: Activate the first tab if no valid active tab is found
$(".oh-tabs__tab").first().addClass("oh-tabs__tab--active fw-bold");
$(".oh-tabs__content").first().addClass("oh-tabs__content--active fw-bold");
// Save the default tab to localStorage
const firstTabTarget = $(".oh-tabs__tab").first().data("target");
localStorage.setItem("activeTabOffboarding", firstTabTarget);
}
}
// Initial application of the active tab
applyActiveTab();
// Add click event listener to dynamically update the active tab
$(".oh-tabs__tab").on("click", function () {
// Remove active classes from all tabs and content
$(".oh-tabs__tab").removeClass("oh-tabs__tab--active fw-bold");
$(".oh-tabs__content").removeClass("oh-tabs__content--active fw-bold");
// Add active class to the clicked tab and corresponding content
$(this).addClass("oh-tabs__tab--active fw-bold");
const target = $(this).data("target");
$(target).addClass("oh-tabs__content--active fw-bold");
// Update the active tab in localStorage
localStorage.setItem("activeTabOffboarding", target);
});
// Reapply active tab after pagination (dynamic content update or reload)
$(document).on("htmx:afterSwap", function () {
applyActiveTab();
});
// Fallback for form submission or full page reload
$(window).on("load", function () {
applyActiveTab();
});
});
</script>

View File

@@ -47,7 +47,7 @@
{% if perms.offboarding.delete_offboarding %}
<li class="oh-dropdown__item">
<a hx-confirm='{% trans "Are you sure want to delete this stage?" %}' hx-post="{% url "delete-offboarding-stage" %}?ids={{stage.grouper.id}}"
hx-target="#offboardingContainer"
hx-target="#objectDetailsModalTarget"
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
</li>
{% endif %}

View File

@@ -5,6 +5,7 @@ from urllib.parse import parse_qs
from django.apps import apps
from django.contrib import messages
from django.contrib.auth.models import User
from django.core.paginator import Paginator
from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect, render
from django.urls import reverse
@@ -110,6 +111,15 @@ def pipeline_grouper(filters={}, offboardings=[]):
return groups
def paginator_qry_offboarding_limited(qryset, page_number):
"""
This method is used to generate common paginator limit.
"""
paginator = Paginator(qryset, 3)
qryset = paginator.get_page(page_number)
return qryset
@login_required
@any_manager_can_enter(
"offboarding.view_offboarding", offboarding_employee_can_enter=True
@@ -118,12 +128,20 @@ def pipeline(request):
"""
Offboarding pipeline view
"""
# Apply filters and pagination
offboardings = PipelineFilter().qs
groups = pipeline_grouper({}, offboardings)
paginated_offboardings = paginator_qry_offboarding_limited(
offboardings, request.GET.get("page")
)
# Group data after pagination
groups = pipeline_grouper({}, paginated_offboardings)
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
stage_forms = {}
for offboarding in offboardings:
for offboarding in paginated_offboardings:
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
filter_dict = parse_qs(request.GET.urlencode())
@@ -132,7 +150,8 @@ def pipeline(request):
request,
"offboarding/pipeline/pipeline.html",
{
"offboardings": groups,
"offboardings": groups, # Grouped data
"paginated_offboardings": paginated_offboardings, # Original paginated object
"employee_filter": PipelineEmployeeFilter(),
"pipeline_filter": PipelineFilter(),
"stage_filter": PipelineStageFilter(),
@@ -153,17 +172,22 @@ def filter_pipeline(request):
This method is used filter offboarding process
"""
offboardings = PipelineFilter(request.GET).qs
groups = pipeline_grouper(request.GET, offboardings)
paginated_offboardings = paginator_qry_offboarding_limited(
offboardings, request.GET.get("page")
)
groups = pipeline_grouper(request.GET, paginated_offboardings)
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
stage_forms = {}
for offboarding in offboardings:
for offboarding in paginated_offboardings:
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
return render(
request,
"offboarding/pipeline/offboardings.html",
{
"offboardings": groups,
"paginated_offboardings": paginated_offboardings,
"stage_forms": stage_forms,
"filter_dict": parse_qs(request.GET.urlencode()),
},
@@ -356,7 +380,7 @@ def delete_stage(request):
messages.error(request, _("Stage not found"))
except OverflowError:
messages.error(request, _("Stage not found"))
return redirect(filter_pipeline)
return HttpResponse("<script>window.location.reload()</script>")
@login_required