This commit is contained in:
+90
-3
@@ -3,10 +3,20 @@ from __future__ import annotations
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db.models import CharField, DecimalField, OuterRef, Q, Subquery
|
||||
from django.db.models import (
|
||||
CharField,
|
||||
DateTimeField,
|
||||
DecimalField,
|
||||
F,
|
||||
JSONField,
|
||||
OuterRef,
|
||||
Q,
|
||||
Subquery,
|
||||
)
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.generic import DetailView, ListView, UpdateView
|
||||
|
||||
@@ -21,6 +31,7 @@ from .services.applications import (
|
||||
track_application_changes,
|
||||
)
|
||||
from .services.feedback import record_feedback
|
||||
from .services.relevance import it_relevance_query
|
||||
|
||||
|
||||
class JobListView(LoginRequiredMixin, ListView):
|
||||
@@ -29,6 +40,15 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
context_object_name = "jobs"
|
||||
paginate_by = 30
|
||||
|
||||
VALID_RECOMMENDATIONS = {
|
||||
ScoreRun.Recommendation.STRONG,
|
||||
ScoreRun.Recommendation.POSSIBLE,
|
||||
ScoreRun.Recommendation.WEAK,
|
||||
ScoreRun.Recommendation.HIDDEN,
|
||||
}
|
||||
VALID_MATCH_FILTERS = {*VALID_RECOMMENDATIONS, "radar", "all"}
|
||||
VALID_SORTS = {"match", "newest", "closing"}
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = JobPosting.objects.select_related("employer").all()
|
||||
profile = SearchProfile.objects.filter(user=self.request.user, is_active=True).first()
|
||||
@@ -48,10 +68,27 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
match_recommendation=Subquery(
|
||||
latest_score.values("recommendation")[:1], output_field=CharField()
|
||||
),
|
||||
match_positives=Subquery(
|
||||
latest_score.values("positives")[:1], output_field=JSONField()
|
||||
),
|
||||
match_concerns=Subquery(
|
||||
latest_score.values("concerns")[:1], output_field=JSONField()
|
||||
),
|
||||
match_hard_exclusions=Subquery(
|
||||
latest_score.values("hard_exclusions")[:1], output_field=JSONField()
|
||||
),
|
||||
match_scored_at=Subquery(
|
||||
latest_score.values("created_at")[:1], output_field=DateTimeField()
|
||||
),
|
||||
)
|
||||
query = self.request.GET.get("q", "").strip()
|
||||
status = self.request.GET.get("status", "active").strip()
|
||||
workplace = self.request.GET.get("workplace", "").strip()
|
||||
focus = self.request.GET.get("focus", "it").strip()
|
||||
recommendation = self.request.GET.get("match", "radar").strip()
|
||||
sort = self.request.GET.get("sort", "match").strip()
|
||||
if recommendation not in self.VALID_MATCH_FILTERS:
|
||||
recommendation = "radar"
|
||||
if query:
|
||||
queryset = queryset.filter(
|
||||
Q(original_title__icontains=query)
|
||||
@@ -63,7 +100,51 @@ class JobListView(LoginRequiredMixin, ListView):
|
||||
queryset = queryset.filter(status=status)
|
||||
if workplace:
|
||||
queryset = queryset.filter(workplace_type=workplace)
|
||||
return queryset.order_by("-first_seen")
|
||||
if focus != "all":
|
||||
queryset = queryset.filter(it_relevance_query())
|
||||
if profile and recommendation == "radar":
|
||||
queryset = queryset.filter(
|
||||
Q(
|
||||
match_recommendation__in=[
|
||||
ScoreRun.Recommendation.STRONG,
|
||||
ScoreRun.Recommendation.POSSIBLE,
|
||||
ScoreRun.Recommendation.WEAK,
|
||||
]
|
||||
)
|
||||
| Q(match_recommendation__isnull=True)
|
||||
)
|
||||
elif profile and recommendation in self.VALID_RECOMMENDATIONS:
|
||||
queryset = queryset.filter(match_recommendation=recommendation)
|
||||
if sort not in self.VALID_SORTS:
|
||||
sort = "match"
|
||||
if sort == "newest":
|
||||
return queryset.order_by("-first_seen", F("match_score").desc(nulls_last=True))
|
||||
if sort == "closing":
|
||||
return queryset.order_by(F("valid_through").asc(nulls_last=True), "-first_seen")
|
||||
return queryset.order_by(F("match_score").desc(nulls_last=True), "-first_seen")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
active_jobs = JobPosting.objects.filter(status=JobPosting.Status.ACTIVE)
|
||||
it_jobs = active_jobs.filter(it_relevance_query())
|
||||
context.update(
|
||||
{
|
||||
"active_profile": SearchProfile.objects.filter(
|
||||
user=self.request.user, is_active=True
|
||||
).first(),
|
||||
"active_job_count": active_jobs.count(),
|
||||
"it_job_count": it_jobs.count(),
|
||||
"filtered_non_it_count": active_jobs.exclude(it_relevance_query()).count(),
|
||||
"current_focus": self.request.GET.get("focus", "it"),
|
||||
"current_match": (
|
||||
self.request.GET.get("match", "radar")
|
||||
if self.request.GET.get("match", "radar") in self.VALID_MATCH_FILTERS
|
||||
else "radar"
|
||||
),
|
||||
"current_sort": self.request.GET.get("sort", "match"),
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class JobDetailView(LoginRequiredMixin, DetailView):
|
||||
@@ -113,7 +194,13 @@ def job_feedback(request, pk):
|
||||
)
|
||||
messages.success(request, "Actie opgeslagen.")
|
||||
next_url = request.POST.get("next")
|
||||
return redirect(next_url or reverse("jobs:detail", kwargs={"pk": pk}))
|
||||
if next_url and url_has_allowed_host_and_scheme(
|
||||
next_url,
|
||||
allowed_hosts={request.get_host()},
|
||||
require_https=request.is_secure(),
|
||||
):
|
||||
return redirect(next_url)
|
||||
return redirect(reverse("jobs:detail", kwargs={"pk": pk}))
|
||||
|
||||
|
||||
class ApplicationListView(LoginRequiredMixin, ListView):
|
||||
|
||||
Reference in New Issue
Block a user