diff --git a/scipost_django/commentaries/forms.py b/scipost_django/commentaries/forms.py index af9c3ed573e0c8b60851ee306eb4d7ae1354d849..0271ad453385703d86bfc3a1f52d2dade8de236a 100644 --- a/scipost_django/commentaries/forms.py +++ b/scipost_django/commentaries/forms.py @@ -6,6 +6,10 @@ from django import forms from django.utils.safestring import mark_safe from django.template.loader import get_template +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Div +from crispy_bootstrap5.bootstrap5 import FloatingField + from .models import Commentary from .constants import COMMENTARY_PUBLISHED, COMMENTARY_PREPRINT @@ -315,7 +319,62 @@ class VetCommentaryForm(forms.Form): class CommentarySearchForm(forms.Form): - """Search for Commentary specified by user""" + author = forms.CharField( + max_length=100, + required=False, + label="On publication with author(s)" + ) + title = forms.CharField( + max_length=100, + required=False, + label="On publication with title" + ) + abstract = forms.CharField( + max_length=1000, + required=False, + label="On publication with abstract" + ) + + def __init__(self, *args, **kwargs): + self.acad_field_slug = kwargs.pop("acad_field_slug") + self.specialty_slug = kwargs.pop("specialty_slug") + super().__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.layout = Layout( + Div( + FloatingField("author"), + FloatingField("title"), + FloatingField("abstract"), + ), + ) + + def search_results(self): + """Return all Commentary objects according to search""" + commentaries = Commentary.objects.vetted() + if self.acad_field_slug and self.acad_field_slug != "all": + commentaries = commentaries.filter(acad_field__slug=self.acad_field_slug) + if self.specialty_slug and self.specialty_slug != "all": + commentaries = commentaries.filter( + specialties__slug=self.specialty_slug + ) + if hasattr(self, "cleaned_data"): + if "title" in self.cleaned_data: + commentaries = commentaries.filter( + title__icontains=self.cleaned_data["title"], + ) + if "abstract" in self.cleaned_data: + commentaries = commentaries.filter( + pub_abstract__icontains=self.cleaned_data["abstract"], + ) + if "author" in self.cleaned_data: + commentaries = commentaries.filter( + author_list__icontains=self.cleaned_data["author"], + ) + return commentaries.order_by("-pub_date") + + +class CommentaryListSearchForm(forms.Form): + """Search for Commentary specified by user (for old CommentaryListView)""" author = forms.CharField(max_length=100, required=False, label="Author(s)") title = forms.CharField(max_length=100, required=False, label="Title") diff --git a/scipost_django/commentaries/models.py b/scipost_django/commentaries/models.py index 24455ae609d3ac18a42ce13e5743e32df89c3fe8..931e64107afa6c3a8cddee00a62fea0105082184 100644 --- a/scipost_django/commentaries/models.py +++ b/scipost_django/commentaries/models.py @@ -16,7 +16,7 @@ from .managers import CommentaryManager class Commentary(TimeStampedModel): """ - A Commentary contains all the contents of a SciPost Commentary page for a given publication. + A Commentary page for a given publication. """ requested_by = models.ForeignKey( diff --git a/scipost_django/commentaries/templates/commentaries/_commentary_card_content.html b/scipost_django/commentaries/templates/commentaries/_commentary_card_content.html index 61d51d71371627c2b9c13f2cd2d6017443880580..aabbaf788b1c93b8e6cecde6cdaf242a70af609f 100644 --- a/scipost_django/commentaries/templates/commentaries/_commentary_card_content.html +++ b/scipost_django/commentaries/templates/commentaries/_commentary_card_content.html @@ -1,4 +1,4 @@ -<div class="card-body px-0"> +<div class="card-body"> <div class="li commentary"> <h3 class="title"><a href="{{ commentary.get_absolute_url }}">{{ commentary.title }}</a></h3> <p class="authors"> diff --git a/scipost_django/commentaries/tests/test_views.py b/scipost_django/commentaries/tests/test_views.py index a1177d7dbeead4b1b6b165105000f7c118c2afdc..0f095812d102d501e87eca845b97550a6f333986 100644 --- a/scipost_django/commentaries/tests/test_views.py +++ b/scipost_django/commentaries/tests/test_views.py @@ -15,7 +15,7 @@ from ..factories import ( UnpublishedCommentaryFactory, UnvettedUnpublishedCommentaryFactory, ) -from ..forms import CommentarySearchForm, RequestPublishedArticleForm +from ..forms import RequestPublishedArticleForm from ..models import Commentary from ..views import RequestPublishedArticle, prefill_using_DOI, RequestArxivPreprint from common.helpers.test import add_groups_and_permissions diff --git a/scipost_django/commentaries/views.py b/scipost_django/commentaries/views.py index 20702e4b0b9e06f8c436ac2caa9a265df62c8bcc..e9ac27b9fcb1494dac860ccc29389a8e31b96d25 100644 --- a/scipost_django/commentaries/views.py +++ b/scipost_django/commentaries/views.py @@ -22,7 +22,7 @@ from .forms import ( ArxivQueryForm, VetCommentaryForm, RequestCommentaryForm, - CommentarySearchForm, + CommentaryListSearchForm, RequestPublishedArticleForm, RequestArxivPreprintForm, CommentSciPostPublication, @@ -224,7 +224,7 @@ def modify_commentary_request(request, commentary_id): class CommentaryListView(PaginationMixin, ListView): model = Commentary - form = CommentarySearchForm + form = CommentaryListSearchForm paginate_by = 10 context_object_name = "commentary_list" diff --git a/scipost_django/comments/forms.py b/scipost_django/comments/forms.py index 29a9eefca96b5fde1e573550468009c1f751c7ef..3419e2d3d087d36286f60dd388b3d2661feffc39 100644 --- a/scipost_django/comments/forms.py +++ b/scipost_django/comments/forms.py @@ -109,13 +109,13 @@ class CommentSearchForm(forms.Form): def search_results(self): comments = Comment.objects.vetted() - if self.acad_field_slug != "all": + if self.acad_field_slug and self.acad_field_slug != "all": comments = comments.filter( Q(submissions__acad_field__slug=self.acad_field_slug) | Q(reports__submission__acad_field__slug=self.acad_field_slug) | Q(commentaries__acad_field__slug=self.acad_field_slug) ) - if self.specialty_slug: + if self.specialty_slug and self.specialty_slug != "all": comments = comments.filter( Q(submissions__specialties__slug=self.specialty_slug) | Q(reports__submission__specialties__slug=self.specialty_slug) diff --git a/scipost_django/scipost/templates/scipost/navbar.html b/scipost_django/scipost/templates/scipost/navbar.html index 743595cf9180c7a988b77c09e0bfff12ce8a0d33..c21604b373534a920bd20a379876ad48156d4068 100644 --- a/scipost_django/scipost/templates/scipost/navbar.html +++ b/scipost_django/scipost/templates/scipost/navbar.html @@ -87,6 +87,65 @@ </a> {% endif %} </li> + + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" href="#" id="MoreDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-trigger="hover">More</a> + <ul class="dropdown-menu" aria-labelledby="MoreDropdown"> + <li> + {% if request.path == '/portal' %} + <button class="nav-link{% if request.GET.tab == 'reports' %} active{% endif %}" + id="reports-tab" + data-bs-toggle="tab" data-bs-target="#reports" + type="button" role="tab" + aria-controls="reports" aria-selected="true"> + Reports + </button> + {% else %} + <a href="{% url 'scipost:portal' %}?tab=reports">Reports</a> + {% endif %} + </li> + <li> + {% if request.path == '/portal' %} + <button class="nav-link{% if request.GET.tab == 'comments' %} active{% endif %}" + id="comments-tab" + data-bs-toggle="tab" data-bs-target="#comments" + type="button" role="tab" + aria-controls="comments" aria-selected="true"> + Comments + </button> + {% else %} + <a href="{% url 'scipost:portal' %}?tab=comments">Comments</a> + {% endif %} + </li> + <li> + {% if request.path == '/portal' %} + <button class="nav-link{% if request.GET.tab == 'commentaries' %} active{% endif %}" + id="commentaries-tab" + data-bs-toggle="tab" data-bs-target="#commentaries" + type="button" role="tab" + aria-controls="commentaries" aria-selected="true"> + Commentaries + </button> + {% else %} + <a href="{% url 'scipost:portal' %}?tab=commentaries">Commentaries</a> + {% endif %} + </li> + <li> + {% if request.path == '/portal' %} + <button class="nav-link{% if request.GET.tab == 'theses' %} active{% endif %}" + id="theses-tab" + data-bs-toggle="tab" data-bs-target="#theses" + type="button" role="tab" + aria-controls="theses" aria-selected="true"> + Theses + </button> + {% else %} + <a href="{% url 'scipost:portal' %}?tab=theses">Theses</a> + {% endif %} + </li> + </ul> + </li> + <!-- <li class="nav-item" role="presentation"> {% if request.path == '/portal' %} diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_commentaries.html b/scipost_django/scipost/templates/scipost/portal/_hx_commentaries.html new file mode 100644 index 0000000000000000000000000000000000000000..716bee0b717a56ec2b8e9d3d0b9f346d802c3059 --- /dev/null +++ b/scipost_django/scipost/templates/scipost/portal/_hx_commentaries.html @@ -0,0 +1,42 @@ +{% load crispy_forms_tags %} + +<div class="p-3 mb-3 bg-light scipost-bar border"> + <h1 class="mb-3">SciPost Commentaries</h1> + <h2> + <a href="{% url 'commentaries:howto' %}">SciPost Commentaries how-to</a> + </h2> + <h2> + <a href="{% url 'commentaries:request_commentary' %}">Request a new Commentary Page</a> + </h2> +</div> + +<div class="d-flex justify-content-between"> + <button class="btn btn-outline-primary" data-bs-toggle="collapse" data-bs-target="#commentariesSearch" aria-expanded="false" aria-controls="commentariesSearch"> + {% include 'bi/search.html' %} Simple search / filter + </button> + <a class="btn btn-outline-primary ms-2" href="{% url 'scipost:search' %}"> + {% include 'bi/binoculars-fill.html' %}... or use our advanced search API {% include 'bi/arrow-right.html' %} + </a> +</div> +<div class="collapse" id="commentariesSearch"> + <div class="card card-body"> + <form + hx-post="{% url 'scipost:portal_hx_commentaries_page' %}?page=1" + hx-trigger="load, keyup delay:500ms, change" + hx-target="#commentaries-search-results" + hx-indicator="#indicator-commentaries-search" + > + <div id="commentaries-search-form">{% crispy commentaries_search_form %}</div> + </form> + </div> + <div id="indicator-commentaries-search" class="htmx-indicator p-2"> + <button class="btn btn-warning" type="button" disabled> + <strong>Loading...</strong> + <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> + </button> + </div> +</div> + +<h2 class="highlight mb-0">Commentaries{% if session_acad_field %} in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}{% else %} (all fields){% endif %}</h2> + +<ul id="commentaries-search-results" class="list-unstyled pool-list mt-2"></ul> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_commentaries_page.html b/scipost_django/scipost/templates/scipost/portal/_hx_commentaries_page.html new file mode 100644 index 0000000000000000000000000000000000000000..1dd4a71a8dadf7a69a8fa5628518e2ef47850afb --- /dev/null +++ b/scipost_django/scipost/templates/scipost/portal/_hx_commentaries_page.html @@ -0,0 +1,28 @@ +{% for commentary in page_obj %} + <li class="list-group-item py-2"> + {% include 'commentaries/_commentary_card_content.html' with commentary=commentary %} + </li> +{% empty %} + <li class="list-group-item py-2"> + None found + </li> +{% endfor %} +{% if page_obj.has_next %} + <li id="next-commentaries-{{ page_obj.number }}"> + <button class="btn btn-primary m-2" type="button" + hx-post="{% url 'scipost:portal_hx_commentaries_page' %}?page={{ page_obj.next_page_number }}" + hx-include="#commentaries-search-form" + hx-target="#next-commentaries-{{ page_obj.number }}" + hx-swap="outerHTML" + hx-indicator="#indicator-commentaries-page-{{ page_obj.number }}" + > + Load page {{ page_obj.next_page_number }} (out of {{ page_obj.paginator.num_pages }}) + </button> + <span id="indicator-commentaries-page-{{ page_obj.number }}" class="htmx-indicator p-2"> + <button class="btn btn-warning" type="button" disabled> + <strong>Loading page {{ page_obj.next_page_number }} out of {{ page_obj.paginator.num_pages }}</strong> + <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> + </button> + </span> + </li> +{% endif %} diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_comments.html b/scipost_django/scipost/templates/scipost/portal/_hx_comments.html index 1875b2b368c20fc8677262fa1fe72cf5c389aad7..87f2163c2c9cab082ec88649e118c775b5ef2f28 100644 --- a/scipost_django/scipost/templates/scipost/portal/_hx_comments.html +++ b/scipost_django/scipost/templates/scipost/portal/_hx_comments.html @@ -27,6 +27,6 @@ </div> </div> -<h2 class="highlight mb-0">Comments on objects in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}</h2> +<h2 class="highlight mb-0">Comments on objects{% if session_acad_field %} in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}{% else %} (all fields){% endif %}</h2> <ul id="comments-search-results" class="list-unstyled pool-list mt-2"></ul> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_reports.html b/scipost_django/scipost/templates/scipost/portal/_hx_reports.html index d4eba9664e9818e8f02dd3b553e3fcbc69fbac81..c12a3f7fa467ede001f66a448616da24bbc7c670 100644 --- a/scipost_django/scipost/templates/scipost/portal/_hx_reports.html +++ b/scipost_django/scipost/templates/scipost/portal/_hx_reports.html @@ -11,10 +11,10 @@ <div class="collapse" id="reportsSearch"> <div class="card card-body"> <form - hx-post="{% url 'scipost:portal_hx_reports_page' %}?page=1" - hx-trigger="load, keyup delay:500ms, change" - hx-target="#reports-search-results" - hx-indicator="#indicator-reports-search" + hx-post="{% url 'scipost:portal_hx_reports_page' %}?page=1" + hx-trigger="load, keyup delay:500ms, change" + hx-target="#reports-search-results" + hx-indicator="#indicator-reports-search" > <div id="reports-search-form">{% crispy reports_search_form %}</div> </form> @@ -27,6 +27,6 @@ </div> </div> -<h2 class="highlight mb-0">Reports on Submissions in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}</h2> +<h2 class="highlight mb-0">Reports on Submissions{% if session_acad_field %} in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}{% else %} (all fields){% endif %}</h2> <ul id="reports-search-results" class="list-unstyled pool-list mt-2"></ul> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_submissions_base.html b/scipost_django/scipost/templates/scipost/portal/_hx_submissions_base.html index 6332e1c885126ed3561870e31f8637ca8c15e908..b97791602e9b533784439ac37c4beafadbd207ee 100644 --- a/scipost_django/scipost/templates/scipost/portal/_hx_submissions_base.html +++ b/scipost_django/scipost/templates/scipost/portal/_hx_submissions_base.html @@ -39,8 +39,9 @@ </h2> </div> <div class="card-body"> - <h3>Please consider contributing a Report so we can minimize delays in editorial processing.</h3> - <p>To do so, please navigate to the Submission's page and click on the <strong>Contribute a Report</strong> link {% if not user.is_authenticated %}(login required){% endif %} + <h3><strong>Please consider contributing one</strong> (even if not explicitly invited to do so)!</h3> + <h3>Authors will be grateful, and our editorial processing will remain free of undue delays.</h3> + <p>To contribute a Report, please navigate to the Submission's page and click on the <strong>Contribute a Report</strong> link {% if not user.is_authenticated %}(login required){% endif %} </div> </div> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_theses.html b/scipost_django/scipost/templates/scipost/portal/_hx_theses.html new file mode 100644 index 0000000000000000000000000000000000000000..f3d2a35457b950e40f0a35a5a6bcd5a2d0a777f2 --- /dev/null +++ b/scipost_django/scipost/templates/scipost/portal/_hx_theses.html @@ -0,0 +1,37 @@ +{% load crispy_forms_tags %} + +<div class="p-3 mb-3 bg-light scipost-bar border"> + <h1 class="mb-3">SciPost Theses</h1> + <h2><a href="{% url 'theses:request_thesislink' %}">Request a new Thesis Link</a></h2> +</div> + +<div class="d-flex justify-content-between"> + <button class="btn btn-outline-primary" data-bs-toggle="collapse" data-bs-target="#thesesSearch" aria-expanded="false" aria-controls="thesesSearch"> + {% include 'bi/search.html' %} Simple search / filter + </button> + <a class="btn btn-outline-primary ms-2" href="{% url 'scipost:search' %}"> + {% include 'bi/binoculars-fill.html' %}... or use our advanced search API {% include 'bi/arrow-right.html' %} + </a> +</div> +<div class="collapse" id="thesesSearch"> + <div class="card card-body"> + <form + hx-post="{% url 'scipost:portal_hx_theses_page' %}?page=1" + hx-trigger="load, keyup delay:500ms, change" + hx-target="#theses-search-results" + hx-indicator="#indicator-theses-search" + > + <div id="theses-search-form">{% crispy theses_search_form %}</div> + </form> + </div> + <div id="indicator-theses-search" class="htmx-indicator p-2"> + <button class="btn btn-warning" type="button" disabled> + <strong>Loading...</strong> + <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> + </button> + </div> +</div> + +<h2 class="highlight mb-0">Thesis links{% if session_acad_field %} in {{ session_acad_field }}: {% if session_specialty %}{{ session_specialty }}{% else %}(all specialties){% endif %}{% else %} (all fields){% endif %}</h2> + +<ul id="theses-search-results" class="list-unstyled pool-list mt-2"></ul> diff --git a/scipost_django/scipost/templates/scipost/portal/_hx_theses_page.html b/scipost_django/scipost/templates/scipost/portal/_hx_theses_page.html new file mode 100644 index 0000000000000000000000000000000000000000..d48e488ab06a04b8dd822ec81c8fd4a3ccc7be52 --- /dev/null +++ b/scipost_django/scipost/templates/scipost/portal/_hx_theses_page.html @@ -0,0 +1,28 @@ +{% for thesislink in page_obj %} + <li class="list-group-item py-2"> + {% include 'theses/_thesislink_card_content.html' with thesislink=thesislink %} + </li> +{% empty %} + <li class="list-group-item py-2"> + None found + </li> +{% endfor %} +{% if page_obj.has_next %} + <li id="next-theses-{{ page_obj.number }}"> + <button class="btn btn-primary m-2" type="button" + hx-post="{% url 'scipost:portal_hx_theses_page' %}?page={{ page_obj.next_page_number }}" + hx-include="#theses-search-form" + hx-target="#next-theses-{{ page_obj.number }}" + hx-swap="outerHTML" + hx-indicator="#indicator-theses-page-{{ page_obj.number }}" + > + Load page {{ page_obj.next_page_number }} (out of {{ page_obj.paginator.num_pages }}) + </button> + <span id="indicator-theses-page-{{ page_obj.number }}" class="htmx-indicator p-2"> + <button class="btn btn-warning" type="button" disabled> + <strong>Loading page {{ page_obj.next_page_number }} out of {{ page_obj.paginator.num_pages }}</strong> + <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> + </button> + </span> + </li> +{% endif %} diff --git a/scipost_django/scipost/templates/scipost/portal/portal.html b/scipost_django/scipost/templates/scipost/portal/portal.html index 2b2929cd412838206ca0a2b41e57f2dd9f1adc56..eb642eecbc627e3d060bfdb4a4e445995561e8ea 100644 --- a/scipost_django/scipost/templates/scipost/portal/portal.html +++ b/scipost_django/scipost/templates/scipost/portal/portal.html @@ -90,6 +90,26 @@ </div> </div> + <div class="tab-pane portal-tab fade{% if request.GET.tab == 'commentaries' %} show active{% endif %}" + id="commentaries" + role="tabpanel" aria-labelledby="commentaries-tab"> + <div hx-get="{% url 'scipost:portal_hx_commentaries' %}" + hx-trigger="{% if request.GET.tab == 'commentaries' %}load, {% endif %}click delay:200ms from:#commentaries-tab, session-acad-field-set from:body, session-specialty-set from:body" + hx-push-url="{% url 'scipost:portal' %}?tab=commentaries" + > + </div> + </div> + + <div class="tab-pane portal-tab fade{% if request.GET.tab == 'theses' %} show active{% endif %}" + id="theses" + role="tabpanel" aria-labelledby="theses-tab"> + <div hx-get="{% url 'scipost:portal_hx_theses' %}" + hx-trigger="{% if request.GET.tab == 'theses' %}load, {% endif %}click delay:200ms from:#theses-tab, session-acad-field-set from:body, session-specialty-set from:body" + hx-push-url="{% url 'scipost:portal' %}?tab=theses" + > + </div> + </div> + </div> {% endblock %} diff --git a/scipost_django/scipost/tests/test_views.py b/scipost_django/scipost/tests/test_views.py index 81d83ed49db5117c2389a8881e059d32dabfb228..2e5f2b550217f530174eb48d45e6e84e625e36c3 100644 --- a/scipost_django/scipost/tests/test_views.py +++ b/scipost_django/scipost/tests/test_views.py @@ -13,7 +13,6 @@ from commentaries.factories import ( CommentaryFactory, UnpublishedCommentaryFactory, ) -from commentaries.forms import CommentarySearchForm from commentaries.models import Commentary from ..factories import ContributorFactory diff --git a/scipost_django/scipost/urls.py b/scipost_django/scipost/urls.py index 419ff30dbb73eee24391485cb0702231ab17b3a1..7b334162560002fd7f7c821c4dd877a1f91beb79 100644 --- a/scipost_django/scipost/urls.py +++ b/scipost_django/scipost/urls.py @@ -124,6 +124,22 @@ urlpatterns = [ views.portal_hx_comments_page, name="portal_hx_comments_page", ), + path( + "portal/_hx_commentaries", + views.portal_hx_commentaries, + name="portal_hx_commentaries" + ), + path( + "portal/_hx_commentaries_page", + views.portal_hx_commentaries_page, + name="portal_hx_commentaries_page", + ), + path("portal/_hx_theses", views.portal_hx_theses, name="portal_hx_theses"), + path( + "portal/_hx_theses_page", + views.portal_hx_theses_page, + name="portal_hx_theses_page", + ), path("_hx_news", views._hx_news, name="_hx_news"), path( "_hx_participates_in", diff --git a/scipost_django/scipost/views.py b/scipost_django/scipost/views.py index 6a9f82732ca364a88b1a222670e420968be54bcc..1be2891a30506ce45f63dcd04bc4b1d4752e6ba3 100644 --- a/scipost_django/scipost/views.py +++ b/scipost_django/scipost/views.py @@ -68,6 +68,7 @@ from .utils import EMAIL_FOOTER, SCIPOST_SUMMARY_FOOTER, SCIPOST_SUMMARY_FOOTER_ from colleges.permissions import fellowship_or_admin_required from commentaries.models import Commentary +from commentaries.forms import CommentarySearchForm from comments.models import Comment from comments.forms import CommentSearchForm from invitations.constants import STATUS_REGISTERED @@ -83,6 +84,7 @@ from profiles.models import Profile from submissions.models import Submission, RefereeInvitation, Report, EICRecommendation from submissions.forms import SubmissionSearchForm, ReportSearchForm from theses.models import ThesisLink +from theses.forms import ThesisSearchForm ########### @@ -344,7 +346,7 @@ def portal_hx_reports_page(request): reports = Report.objects.accepted() if session_acad_field_slug and session_acad_field_slug != "all": reports = reports.filter(submission__acad_field__slug=session_acad_field_slug) - if session_specialty_slug: + if session_specialty_slug and session_specialty_slug != "all": reports = reports.filter( submission__specialties__slug=session_specialty_slug ) @@ -382,7 +384,7 @@ def portal_hx_comments_page(request): | Q(reports__submission__acad_field__slug=session_acad_field_slug) | Q(commentaries__acad_field__slug=session_acad_field_slug) ) - if session_specialty_slug: + if session_specialty_slug and session_specialty_slug != "all": comments = comments.filter( Q(submissions__specialties__slug=session_specialty_slug) | Q(reports__submission__specialties__slug=session_specialty_slug) @@ -395,6 +397,58 @@ def portal_hx_comments_page(request): return render(request, "scipost/portal/_hx_comments_page.html", context) +def portal_hx_commentaries(request): + form = CommentarySearchForm( + acad_field_slug=request.session.get("session_acad_field_slug", None), + specialty_slug=request.session.get("session_specialty_slug", None), + ) + context = {"commentaries_search_form": form} + return render(request, "scipost/portal/_hx_commentaries.html", context) + + +def portal_hx_commentaries_page(request): + session_acad_field_slug = request.session.get("session_acad_field_slug", None) + session_specialty_slug = request.session.get("session_specialty_slug", None) + form = CommentarySearchForm( + request.POST or None, + acad_field_slug=session_acad_field_slug, + specialty_slug=session_specialty_slug, + ) + form.is_valid() # trigger validation to get filtering + commentaries = form.search_results() + paginator = Paginator(commentaries, 10) + page_nr = request.GET.get("page") + page_obj = paginator.get_page(page_nr) + context = {"page_obj": page_obj} + return render(request, "scipost/portal/_hx_commentaries_page.html", context) + + +def portal_hx_theses(request): + form = ThesisSearchForm( + acad_field_slug=request.session.get("session_acad_field_slug", None), + specialty_slug=request.session.get("session_specialty_slug", None), + ) + context = {"theses_search_form": form} + return render(request, "scipost/portal/_hx_theses.html", context) + + +def portal_hx_theses_page(request): + session_acad_field_slug = request.session.get("session_acad_field_slug", None) + session_specialty_slug = request.session.get("session_specialty_slug", None) + form = ThesisSearchForm( + request.POST or None, + acad_field_slug=session_acad_field_slug, + specialty_slug=session_specialty_slug, + ) + form.is_valid() # trigger validation to get filtering + theses = form.search_results() + paginator = Paginator(theses, 10) + page_nr = request.GET.get("page") + page_obj = paginator.get_page(page_nr) + context = {"page_obj": page_obj} + return render(request, "scipost/portal/_hx_theses_page.html", context) + + def _hx_news(request): if NewsItem.objects.homepage().exists(): latest_newsitem_id = NewsItem.objects.homepage().order_by("-date").first().id diff --git a/scipost_django/submissions/forms.py b/scipost_django/submissions/forms.py index b3b1ee705a76626c6efc3d2dd0002de9a976748d..9a33606db47178ba7f23c0d3ee8184a22cdc66d6 100644 --- a/scipost_django/submissions/forms.py +++ b/scipost_django/submissions/forms.py @@ -143,7 +143,7 @@ class SubmissionSearchForm(forms.Form): Return all Submission objects fitting search criteria. """ submissions = Submission.objects.public_newest().unpublished() - if self.acad_field_slug != "all": + if self.acad_field_slug and self.acad_field_slug != "all": submissions = submissions.filter(acad_field__slug=self.acad_field_slug) if self.specialty_slug and self.specialty_slug != "all": submissions = submissions.filter(specialties__slug=self.specialty_slug) @@ -412,9 +412,9 @@ class ReportSearchForm(forms.Form): def search_results(self): reports = Report.objects.accepted() - if self.acad_field_slug != "all": + if self.acad_field_slug and self.acad_field_slug != "all": reports = reports.filter(submission__acad_field__slug=self.acad_field_slug) - if self.specialty_slug: + if self.specialty_slug and self.specialty_slug != "all": reports = reports.filter( submission__specialties__slug=self.specialty_slug ) diff --git a/scipost_django/theses/forms.py b/scipost_django/theses/forms.py index 1120deb0cf59e3d2d004f114e77b5215f962e923..70ef57f20d4928cf63532100015210b1bfa44062 100644 --- a/scipost_django/theses/forms.py +++ b/scipost_django/theses/forms.py @@ -7,6 +7,10 @@ from django.contrib.sites.models import Site from django.core.mail import EmailMessage from django.template.loader import render_to_string +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Div +from crispy_bootstrap5.bootstrap5 import FloatingField + from scipost.models import Contributor from scipost.utils import build_absolute_uri_using_site @@ -138,3 +142,55 @@ class ThesisLinkSearchForm(forms.Form): max_length=1000, required=False, label="Abstract" ) supervisor = forms.CharField(max_length=100, required=False, label="Supervisor") + + +class ThesisSearchForm(forms.Form): + author = forms.CharField(max_length=100, required=False, label="Author") + title = forms.CharField(max_length=100, label="Title", required=False) + abstract = forms.CharField( + max_length=1000, required=False, label="Abstract" + ) + supervisor = forms.CharField(max_length=100, required=False, label="Supervisor") + + def __init__(self, *args, **kwargs): + self.acad_field_slug = kwargs.pop("acad_field_slug") + self.specialty_slug = kwargs.pop("specialty_slug") + super().__init__(*args, **kwargs) + self.helper = FormHelper() + self.helper.layout = Layout( + Div( + FloatingField("author"), + FloatingField("title"), + FloatingField("abstract"), + FloatingField("supervisor"), + ), + ) + + def search_results(self): + """Return all ThesisLink objects fitting search""" + theses = ThesisLink.objects.vetted() + if self.acad_field_slug and self.acad_field_slug != "all": + theses = theses.filter(acad_field__slug=self.acad_field_slug) + if self.specialty_slug and self.specialty_slug != "all": + theses = theses.filter( + specialties__slug=self.specialty_slug + ) + if hasattr(self, "cleaned_data"): + if "title" in self.cleaned_data: + theses = theses.filter( + title__icontains=self.cleaned_data["title"], + ) + len(theses) + if "abstract" in self.cleaned_data: + theses = theses.filter( + abstract__icontains=self.cleaned_data["abstract"], + ) + if "author" in self.cleaned_data: + theses = theses.filter( + author__icontains=self.cleaned_data["author"], + ) + if "supervisor" in self.cleaned_data: + theses = theses.filter( + supervisor__icontains=self.cleaned_data["supervisor"], + ) + return theses.order_by("-defense_date") diff --git a/scipost_django/theses/templates/theses/_thesislink_card_content.html b/scipost_django/theses/templates/theses/_thesislink_card_content.html index 7d37452df408b9d84ef5fcff22b79988ad86cf5b..e1520ae23838dcedbb91762c9ff848def148c8ec 100644 --- a/scipost_django/theses/templates/theses/_thesislink_card_content.html +++ b/scipost_django/theses/templates/theses/_thesislink_card_content.html @@ -1,4 +1,4 @@ -<div class="card-body px-0"> +<div class="card-body"> <div class="li thesis"> <h3 class="specialties">{{ thesislink.acad_field }}</h3> <ul class="list-inline">