diff --git a/commentaries/templates/commentaries/commentary_list.html b/commentaries/templates/commentaries/commentary_list.html index 40efb8b4b21db67137944de2ca4905e42c818b2e..37a6123d03b8432b7871102fcc4f4ba4f70eaa91 100644 --- a/commentaries/templates/commentaries/commentary_list.html +++ b/commentaries/templates/commentaries/commentary_list.html @@ -71,33 +71,28 @@ {% else %} <h2>Search results:</h3> {% endif %} - {% if commentary_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for object in commentary_list %} - <li class="list-group-item"> - {% include 'commentaries/_commentary_card_content.html' with commentary=object %} - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for object in commentary_list %} + <li class="list-group-item"> + {% include 'commentaries/_commentary_card_content.html' with commentary=object %} + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/commentaries/views.py b/commentaries/views.py index dcbf31f3ff6c8fc1a92becea8812706c7e13e541..dd60ecd04fe4c11fe0b4be93ae4f4db60f8d9a6b 100644 --- a/commentaries/views.py +++ b/commentaries/views.py @@ -16,6 +16,7 @@ from .forms import DOIToQueryForm, ArxivQueryForm, VetCommentaryForm, RequestCom from comments.models import Comment from comments.forms import CommentForm +from scipost.mixins import PaginationMixin import strings @@ -190,7 +191,7 @@ def modify_commentary_request(request, commentary_id): return render(request, 'commentaries/modify_commentary_request.html', context) -class CommentaryListView(ListView): +class CommentaryListView(PaginationMixin, ListView): model = Commentary form = CommentarySearchForm paginate_by = 10 diff --git a/scipost/mixins.py b/scipost/mixins.py new file mode 100644 index 0000000000000000000000000000000000000000..49dec74f4c44887c0667fbfb9caebf1128e4739b --- /dev/null +++ b/scipost/mixins.py @@ -0,0 +1,15 @@ +from .paginator import SciPostPaginator + + +class PaginationMixin(object): + """ + Mixin for generic class-based views (e.g. django.views.generic.ListView) + """ + paginator_class = SciPostPaginator + + # def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True): + # # Pass the request object to the paginator to keep the parameters in the + # # url querystring ("?page=2&old_param=...") + # request = self.request + # return self.paginator_class(queryset, per_page, orphans=orphans, + # allow_empty_first_page=allow_empty_first_page, request=request) diff --git a/scipost/paginator.py b/scipost/paginator.py new file mode 100644 index 0000000000000000000000000000000000000000..dc253f22e00b765ea1f8fc2b8000417215ad8e0f --- /dev/null +++ b/scipost/paginator.py @@ -0,0 +1,42 @@ +from django.core.paginator import Paginator, Page + +PAGE_RANGE_DISPLAYED = 10 +MARGIN_PAGES_DISPLAYED = 1 +SHOW_FIRST_PAGE_WHEN_INVALID = True + + +class SciPostPaginator(Paginator): + def _get_page(self, *args, **kwargs): + return SciPostPage(*args, **kwargs) + + +class SciPostPage(Page): + def pages(self): + """ + Custom pages set that tweaks the range of pages to be shown in the paginator. + """ + if self.paginator.num_pages <= PAGE_RANGE_DISPLAYED: + return range(1, self.paginator.num_pages + 1) + result = [] + left_side = PAGE_RANGE_DISPLAYED / 2 + right_side = PAGE_RANGE_DISPLAYED - left_side + if self.number > self.paginator.num_pages - PAGE_RANGE_DISPLAYED / 2: + right_side = self.paginator.num_pages - self.number + left_side = PAGE_RANGE_DISPLAYED - right_side + elif self.number < PAGE_RANGE_DISPLAYED / 2: + left_side = self.number + right_side = PAGE_RANGE_DISPLAYED - left_side + for page in range(1, self.paginator.num_pages + 1): + if page <= MARGIN_PAGES_DISPLAYED: + result.append(page) + continue + if page > self.paginator.num_pages - MARGIN_PAGES_DISPLAYED: + result.append(page) + continue + if (page >= self.number - left_side) and (page <= self.number + right_side): + result.append(page) + continue + if result[-1]: + result.append(None) + + return result diff --git a/submissions/templates/submissions/submissions.html b/submissions/templates/submissions/submissions.html index 42aa6edd773874840173c4c7c46793bd7098fb77..05e114e3f2e255678c6c9b80c6ce870f309e436f 100644 --- a/submissions/templates/submissions/submissions.html +++ b/submissions/templates/submissions/submissions.html @@ -50,49 +50,30 @@ {% else %} <h2>Search results:</h3> {% endif %} - {% if object_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for submission in object_list %} - <li class="list-group-item"> - <div class="card-body px-0"> - {% include 'partials/submissions/submission_card_content.html' with submission=submission %} - </div> - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} - </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} <div class="col-12"> - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} + <ul class="list-group list-group-flush"> + {% for submission in object_list %} + <li class="list-group-item"> + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=submission %} + </div> + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/submissions/views.py b/submissions/views.py index 065563200c62dec3911dd9973effba3eae5ebb89..14a1ef4c7614f98c6d1b77993f6de87283a6bf42 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -35,6 +35,7 @@ from .utils import SubmissionUtils from mails.views import MailEditingSubView from scipost.forms import ModifyPersonalMessageForm, RemarkForm +from scipost.mixins import PaginationMixin from scipost.models import Contributor, Remark, RegistrationInvitation from scipost.utils import Utils from scipost.permissions import is_tester @@ -122,7 +123,7 @@ def prefill_using_arxiv_identifier(request): return render(request, 'submissions/prefill_using_identifier.html', context) -class SubmissionListView(ListView): +class SubmissionListView(PaginationMixin, ListView): model = Submission template_name = 'submissions/submissions.html' form = SubmissionSearchForm diff --git a/templates/partials/pagination.html b/templates/partials/pagination.html index 5a5df28ed017085af07fed056243f1c0c71eb9c1..28924103800f75c6f1e860c481ffe9ada73ca353 100644 --- a/templates/partials/pagination.html +++ b/templates/partials/pagination.html @@ -2,37 +2,27 @@ <div class="text-center"> {% if page_obj.has_previous %} - <a class="btn btn-secondary" href="?{% url_replace page=page_obj.previous_page_number %}"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</a> + <a class="" href="?{% url_replace page=page_obj.previous_page_number %}"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</a> {% else %} - <span class="btn btn-secondary text-muted"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</span> + <span class="text-muted"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</span> {% endif %} - {% if page_obj.number > 1 %} - {% if page_obj.number > 2 %} - <a href="?{% url_replace page=1 %}" class="btn px-1">1</a> - {% if page_obj.number > 3 %} - ... - {% endif %} - {% endif %} - <a href="?{% url_replace page=page_obj.previous_page_number %}" class="btn px-1">{{ page_obj.previous_page_number }}</a> - {% endif %} - - <span class="btn btn-info">{{ page_obj.number }}</span> - {% if page_obj.number < page_obj.paginator.num_pages %} - <a href="?{% url_replace page=page_obj.next_page_number %}" class="btn px-1">{{ page_obj.next_page_number }}</a> - - {% if page_obj.number|add:"2" < page_obj.paginator.num_pages %} + {% for page in page_obj.pages %} + {% if page %} + {% if page == page_obj.number %} + <span class="current page">{{ page }}</span> + {% else %} + <a href="?{% url_replace page=page %}" class="page">{{ page }}</a> + {% endif %} + {% else %} ... {% endif %} - {% if page_obj.number|add:"1" < page_obj.paginator.num_pages %} - <a href="?{% url_replace page=page_obj.paginator.num_pages %}" class="btn px-1">{{ page_obj.paginator.num_pages }}</a> - {% endif %} - {% endif %} + {% endfor %} {% if page_obj.has_next %} - <a class="btn btn-secondary" href="?{% url_replace page=page_obj.next_page_number %}">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></a> + <a class="" href="?{% url_replace page=page_obj.next_page_number %}">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></a> {% else %} - <span class="btn btn-secondary text-muted">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></span> + <span class="text-muted">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></span> {% endif %} </div> diff --git a/theses/templates/theses/thesislink_list.html b/theses/templates/theses/thesislink_list.html index d2dd2e2e0cde33324b2812749a0d14e23905d649..0e417c3656c7a5f784afd6f3172d5f58c014efc2 100644 --- a/theses/templates/theses/thesislink_list.html +++ b/theses/templates/theses/thesislink_list.html @@ -53,34 +53,28 @@ {% else %} <h2>Search results:</h3> {% endif %} - - {% if object_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for thesislink in object_list %} - <li class="list-group-item"> - {% include 'theses/_thesislink_card_content.html' with thesislink=thesislink %} - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for thesislink in object_list %} + <li class="list-group-item"> + {% include 'theses/_thesislink_card_content.html' with thesislink=thesislink %} + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/theses/views.py b/theses/views.py index 285bda18f792efc3f376a78938a548b562825a71..1bf37ce05b79a2fe4cdbbf6269fe051eb4b40c8c 100644 --- a/theses/views.py +++ b/theses/views.py @@ -14,6 +14,7 @@ from .models import ThesisLink from .forms import RequestThesisLinkForm, ThesisLinkSearchForm, VetThesisLinkForm from comments.forms import CommentForm +from scipost.mixins import PaginationMixin import strings @@ -78,7 +79,7 @@ class VetThesisLink(UpdateView): return HttpResponseRedirect(self.get_success_url()) -class ThesisListView(ListView): +class ThesisListView(PaginationMixin, ListView): model = ThesisLink form = ThesisLinkSearchForm paginate_by = 10