diff --git a/scipost_django/ontology/forms.py b/scipost_django/ontology/forms.py index fac57321895e3bee23669b2dbf7df4cbed1abc20..57fbe4b5e7b5f526bd2441f4a269dac81d3c7c50 100644 --- a/scipost_django/ontology/forms.py +++ b/scipost_django/ontology/forms.py @@ -29,6 +29,47 @@ def academic_field_slug_choices(): return choices +class AcadFieldSpecialtyForm(forms.Form): + """ + A form to select an academic field and its associated specialties. + """ + + acad_field_slug = forms.ChoiceField( + label="Academic Field", choices=academic_field_slug_choices() + ) + specialty_slug = forms.ChoiceField(label="Specialty", required=False) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Delete specialty_slug field from the form if acad_field_slug is not set + acad_field_slug = self.data.get("acad_field_slug") + if acad_field_slug is None or acad_field_slug == "all": + del self.fields["specialty_slug"] + else: + self.set_specialty_choices() + + self.helper = FormHelper(self) + self.helper.layout = Layout( + Div( + FloatingField("specialty_slug"), + FloatingField("acad_field_slug"), + css_class="d-flex flex-row gap-2", + ) + ) + + def set_specialty_choices(self): + acad_field_slug = self.data.get("acad_field_slug") + specialties = ( + Specialty.objects.filter(acad_field__slug=acad_field_slug) + if acad_field_slug + else Specialty.objects.none() + ) + self.fields["specialty_slug"].choices = [("all", "All specialties")] + [ + (specialty.slug, str(specialty)) for specialty in specialties.all() + ] + + class SessionAcademicFieldForm(forms.Form): acad_field_slug = forms.ChoiceField( label="Academic Field", choices=academic_field_slug_choices() diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_home.html b/scipost_django/scipost/templates/scipost/portal/_hx_home.html index 16c5d698f558fe0496a981dc9a47d728c8a3dd6e..37ae427d6285d99253d9b66ecc1406e8c2c5ac77 100644 --- a/scipost_django/scipost/templates/scipost/portal/_hx_home.html +++ b/scipost_django/scipost/templates/scipost/portal/_hx_home.html @@ -8,15 +8,9 @@ <br> serving professional scientists worldwide.</h2> - <div class="publications"> - <h2 class="highlight">Selected publications</h2> - - <div class="publication-list"> - {% for publication in publications %} - {% include 'journals/_publication_li_content-alt.html' with publication=publication %} - {% endfor %} - </div> - </div> + <div hx-trigger="load once" + hx-swap="outerHTML" + hx-get="{% url "scipost:portal_hx_recent_publications" %}"></div> </div> <div class="col-md-4"> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_recent_publications.html b/scipost_django/scipost/templates/scipost/portal/_hx_recent_publications.html new file mode 100644 index 0000000000000000000000000000000000000000..5ec75e18e07404f95d466fc4015f89aabd21f6ca --- /dev/null +++ b/scipost_django/scipost/templates/scipost/portal/_hx_recent_publications.html @@ -0,0 +1,26 @@ +{% load crispy_forms_tags %} + +<div class="publications"> + <h2 class="highlight px-3 d-flex flex-row justify-content-between align-items-center"> + <a href="{% url "journals:publications" %}" class="text-body">Recent publications</a> + <form hx-trigger="input change" + hx-target="div.publications" + hx-swap="outerHTML" + hx-post="{% url "scipost:portal_hx_recent_publications" %}"> + {% crispy form %} + </form> + </h2> + + <div class="publication-list"> + + {% for publication in publications %} + {% include 'journals/_publication_li_content-alt.html' with publication=publication %} + {% empty %} + <div class="publication"> + <p class="fs-3 px-2">No publications found.</p> + </div> + + {% endfor %} + + </div> +</div> diff --git a/scipost_django/scipost/urls.py b/scipost_django/scipost/urls.py index c268f8b351d1abcb101497418f30fdf97d245c9e..ea01c93d51c59f17aba7ad72ec18a808211dcfde 100644 --- a/scipost_django/scipost/urls.py +++ b/scipost_django/scipost/urls.py @@ -91,6 +91,11 @@ urlpatterns = [ views.portal_hx_publications, name="portal_hx_publications", ), + path( + "portal/_hx_recent_publications", + views.portal_hx_recent_publications, + name="portal_hx_recent_publications", + ), path( "portal/_hx_publications_page", views.portal_hx_publications_page, diff --git a/scipost_django/scipost/views.py b/scipost_django/scipost/views.py index c1b56bd392beba1d9f4693faf568522368324b96..fca3f7b8f94ebe8232fb20eede4b8b604168b462 100644 --- a/scipost_django/scipost/views.py +++ b/scipost_django/scipost/views.py @@ -44,6 +44,7 @@ from django.views.static import serve from dal import autocomplete from guardian.decorators import permission_required import requests +from ontology.forms import AcadFieldSpecialtyForm from scipost.permissions import permission_required_htmx, HTMXResponse from .constants import SciPost_from_addresses_dict, NORMAL_CONTRIBUTOR @@ -219,6 +220,27 @@ def portal_hx_home(request): return render(request, "scipost/portal/_hx_home.html", context) +def portal_hx_recent_publications(request): + form = AcadFieldSpecialtyForm(request.POST or None) + acad_field = request.POST.get("acad_field_slug", None) + specialty = request.POST.get("specialty_slug", None) + + publications = Publication.objects.published() + filter_q = Q() + if acad_field and acad_field != "all": + filter_q &= Q(acad_field__slug=acad_field) + if specialty and specialty != "all": + filter_q &= Q(specialties__slug=specialty) + + publications = ( + publications.filter(filter_q) + .order_by("-publication_date") + .prefetch_related("in_issue__in_journal", "specialties", "collections__series") + ) + context = {"publications": publications[:5], "form": form} + return render(request, "scipost/portal/_hx_recent_publications.html", context) + + @login_required @user_passes_test(is_edadmin_or_active_fellow) def portal_hx_tasklist(request):