[FIX] OFFBOARDING: Fixed the issues in Offboarding creation, stage creation and added pagination and style fixes
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user