From af768b6ac1ee92c8fac4e5fe96eb62a235e8ecdd Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 9 Jun 2026 23:17:01 +0000 Subject: [PATCH] Vv --- core/__pycache__/views.cpython-311.pyc | Bin 11861 -> 12893 bytes core/templates/core/job_list.html | 16 +++++++++ core/templates/core/ops_dashboard.html | 16 +++++++++ core/views.py | 45 ++++++++++++++++++------- 4 files changed, 64 insertions(+), 13 deletions(-) diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 5c1f0c4e2c4ef1411e1076c9b1952c5be227487c..09ca623119931654abd6337b3a138633772b2f52 100644 GIT binary patch delta 3862 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 diff --git a/core/templates/core/job_list.html b/core/templates/core/job_list.html index a8e6f80..9327b35 100644 --- a/core/templates/core/job_list.html +++ b/core/templates/core/job_list.html @@ -44,6 +44,9 @@
+ @@ -59,6 +62,19 @@ {% endfor %} + {% if jobs.has_other_pages %} + + {% endif %} {% else %}
diff --git a/core/templates/core/ops_dashboard.html b/core/templates/core/ops_dashboard.html index 92ce73a..84d8c4d 100644 --- a/core/templates/core/ops_dashboard.html +++ b/core/templates/core/ops_dashboard.html @@ -44,6 +44,9 @@
+
@@ -81,6 +84,19 @@ + {% if sources.has_other_pages %} + + {% endif %} {% else %}
No sources yet. Register the first portal, agency, or company careers page.
{% endif %} diff --git a/core/views.py b/core/views.py index c87ced7..733eebb 100644 --- a/core/views.py +++ b/core/views.py @@ -1,5 +1,6 @@ from django.contrib import messages from django.db.models import Count, Q +from django.core.paginator import Paginator from django.shortcuts import get_object_or_404, redirect, render from django.utils import timezone @@ -96,20 +97,28 @@ def job_list(request): family = request.GET.get("family", "").strip() source_status = request.GET.get("source_status", "").strip() - jobs = JobPosting.objects.select_related("source").filter(is_active=True) + jobs_qs = JobPosting.objects.select_related("source").filter(is_active=True) if query: - jobs = jobs.filter( + jobs_qs = jobs_qs.filter( Q(title__icontains=query) | Q(company__icontains=query) | Q(location__icontains=query) | Q(description__icontains=query) ) if contract: - jobs = jobs.filter(contract_type=contract) + jobs_qs = jobs_qs.filter(contract_type=contract) if family: - jobs = jobs.filter(source__family=family) + jobs_qs = jobs_qs.filter(source__family=family) if source_status: - jobs = jobs.filter(source__status=source_status) + jobs_qs = jobs_qs.filter(source__status=source_status) + + paginator = Paginator(jobs_qs, 9) + page_number = request.GET.get("page") + jobs = paginator.get_page(page_number) + + filters = request.GET.copy() + filters.pop("page", None) + current_filters_qs = filters.urlencode() context = { **_meta("Search Job Offers", "Search normalized job offers collected for Dijon and nearby opportunities."), @@ -121,7 +130,8 @@ def job_list(request): "contract_choices": JobPosting.ContractType.choices, "family_choices": JobSource.Family.choices, "source_status_choices": JobSource.Status.choices, - "result_count": jobs.count(), + "result_count": jobs_qs.count(), + "current_filters_qs": current_filters_qs, } return render(request, "core/job_list.html", context) @@ -144,13 +154,21 @@ def ops_dashboard(request): family = request.GET.get("family", "").strip() status = request.GET.get("status", "").strip() - sources = JobSource.objects.annotate(job_total=Count("jobs")).order_by("family", "name") + sources_qs = JobSource.objects.annotate(job_total=Count("jobs")).order_by("family", "name") if query: - sources = sources.filter(Q(name__icontains=query) | Q(owner__icontains=query) | Q(url__icontains=query)) + sources_qs = sources_qs.filter(Q(name__icontains=query) | Q(owner__icontains=query) | Q(url__icontains=query)) if family: - sources = sources.filter(family=family) + sources_qs = sources_qs.filter(family=family) if status: - sources = sources.filter(status=status) + sources_qs = sources_qs.filter(status=status) + + paginator = Paginator(sources_qs, 8) + page_number = request.GET.get("page") + sources = paginator.get_page(page_number) + + filters = request.GET.copy() + filters.pop("page", None) + current_filters_qs = filters.urlencode() recent_jobs = ( JobPosting.objects.select_related("source") @@ -166,8 +184,8 @@ def ops_dashboard(request): .annotate(total=Count("id")) .order_by("status") ) - needs_attention = sources.filter(status=JobSource.Status.ERROR).count() - stale_sources = sources.filter(last_checked_at__isnull=True).count() + needs_attention = sources_qs.filter(status=JobSource.Status.ERROR).count() + stale_sources = sources_qs.filter(last_checked_at__isnull=True).count() return render( request, "core/ops_dashboard.html", @@ -183,11 +201,12 @@ def ops_dashboard(request): "needs_attention": needs_attention, "stale_sources": stale_sources, "active_jobs": JobPosting.objects.filter(is_active=True).count(), - "total_sources": sources.count(), + "total_sources": sources_qs.count(), "query": query, "family": family, "status": status, "family_choices": JobSource.Family.choices, "status_choices": JobSource.Status.choices, + "current_filters_qs": current_filters_qs, }, )