diff --git a/scipost_django/common/templates/_hx_dynsel_list.html b/scipost_django/common/templates/_hx_dynsel_list.html new file mode 100644 index 0000000000000000000000000000000000000000..bfb58cba569fb0a4d353d18c1cbd2c37ab0b75b1 --- /dev/null +++ b/scipost_django/common/templates/_hx_dynsel_list.html @@ -0,0 +1,18 @@ +{% load common_extras %} + +<ul class="list list-unstyled"> + {% for object in objects|slice:":11" %} + {% if forloop.counter == 11 %} + <li> ...</li> + {% else %} + <li class="m-1"> + <a + hx-get="{% dynsel_action_url object %}" + hx-target="#fellowships" + > + {{ fellowship }} + </a> + </li> + {% endif %} + {% endfor %} +</ul> diff --git a/scipost_django/common/templatetags/common_extras.py b/scipost_django/common/templatetags/common_extras.py new file mode 100644 index 0000000000000000000000000000000000000000..d8951f44dbbaaa90338341107ad68605c90e7267 --- /dev/null +++ b/scipost_django/common/templatetags/common_extras.py @@ -0,0 +1,24 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django import template +from django.urls import reverse + + +register = template.Library() + + +@register.simple_tag(takes_context=True) +def action_url(context, **extra_kwargs): + kwargs = context["action_url_base_kwargs"] + kwargs.update(extra_kwargs) + return reverse(context["action_url_name"], kwargs=kwargs) + + +@register.filter +def replace(text, args): + if len(args.split("|")) != 2: + return text + a, b = args.split("|") + return text.replace(a, b) diff --git a/scipost_django/edadmin/converters.py b/scipost_django/edadmin/converters.py new file mode 100644 index 0000000000000000000000000000000000000000..99bbe636df60ac7bfec64b4914fe7d63f2b48445 --- /dev/null +++ b/scipost_django/edadmin/converters.py @@ -0,0 +1,11 @@ +__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.urls.converters import SlugConverter + + +class SubmissionStageSlugConverter(SlugConverter): + def __init__(self): + from submissions.models import Submission + self.regex = "|".join(s for s in Submission.STAGE_SLUGS) diff --git a/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html b/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html index d7515170083b3bcc4ae55eb1781e2683b1e8a829..a2e5a871c616bd8e08c2d38e607016977d12d781 100644 --- a/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html +++ b/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html @@ -1,11 +1,12 @@ +<h3 class="m-4">{{ submissions|length }} Submissions in this stage</h3> {% for submission in submissions %} <details id="submission-{{ submission.pk }}-details" class="border border-2 m-4" > <summary class="px-4 py-2 bg-primary bg-opacity-10"> - <ul class="list list-inline"> - <li class="list-inline-item"> + <div class="row"> + <div class="col col-lg-10"> <table> <tbody> <tr> @@ -19,14 +20,14 @@ </tr> </tbody> </table> - </li> - <li class="list-inline-item float-end"> + </div> + <div class="col col-lg-2"> <ul class="list list-unstyled"> <li class="mb-2"><a href="{% url 'submissions:submission' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}" target="_blank">{% include "bi/arrow-right-square-fill.html" %}submission page</a></li> <li class="mb-2"><a href="{% url 'submissions:editorial_page' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}" target="_blank" class="text-danger">{% include "bi/arrow-right-square-fill.html" %}editorial page</a></li> </ul> - </li> - </ul> + </div> + </div> </summary> <div id="submission-{{ submission.pk }}-details-contents" hx-get="{% url 'edadmin:_hx_submission_details_contents' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}" diff --git a/scipost_django/edadmin/templates/edadmin/edadmin.html b/scipost_django/edadmin/templates/edadmin/edadmin.html index 24be2ccd0974ad2adba0d306e9bc4f6e8e06cd47..9da448b91b3443c3c409c1c65a4e54fc7e54c6a3 100644 --- a/scipost_django/edadmin/templates/edadmin/edadmin.html +++ b/scipost_django/edadmin/templates/edadmin/edadmin.html @@ -1,5 +1,7 @@ {% extends 'scipost/base.html' %} +{% load common_extras %} + {% block breadcrumb %} <div class="breadcrumb-container"> <div class="container"> @@ -16,27 +18,27 @@ {% block content %} - - <details class="border border-2 my-4" - id="incoming-details" - > - <summary class="bg-primary bg-opacity-10 px-4 py-2"> - <h1>Incoming</h1> - </summary> - <span id="incoming" - hx-get="{% url 'edadmin:_hx_incoming_list' %}" - hx-swap="outerHTML" - hx-trigger="toggle once from:#incoming-details" - hx-indicator="#indicator-submissions-incoming" - ></span> - <span id="indicator-submissions-incoming" class="htmx-indicator"> - <button class="m-2 btn btn-sm btn-warning" type="button" disabled> - <strong>Loading incoming Submissions...</strong> - <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> - </button> - </span> - </details> - + {% for stage in stages %} + <details class="border border-2 my-4" + id="{{ stage }}-details" + > + <summary class="bg-primary bg-opacity-10 px-4 py-2"> + <h1>{{ stage|capfirst|replace:"_| " }}</h1> + </summary> + <span id="{{ stage }}-details-contents" + hx-get="{% url 'edadmin:_hx_submissions_in_stage' stage=stage %}" + hx-swap="outerHTML" + hx-trigger="toggle once from:#{{ stage }}-details" + hx-indicator="#indicator-submissions-{{ stage }}" + ></span> + <span id="indicator-submissions-{{ stage }}" class="htmx-indicator"> + <button class="m-2 btn btn-sm btn-warning" type="button" disabled> + <strong>Loading Submissions in stage {{ stage|replace:"_| " }}...</strong> + <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> + </button> + </span> + </details> + {% endfor %} {% endblock content %} {% block footer_script %} diff --git a/scipost_django/edadmin/urls/__init__.py b/scipost_django/edadmin/urls/__init__.py index c1ae4f9db0478f0d00e69fc7fb4fd767c9864d01..f5109a296c551beca0518c2d193c4e14b5e87974 100644 --- a/scipost_django/edadmin/urls/__init__.py +++ b/scipost_django/edadmin/urls/__init__.py @@ -2,14 +2,22 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" -from django.urls import include, path +from django.urls import include, path, register_converter +from ..converters import SubmissionStageSlugConverter from ..views import base app_name = "edadmin" +register_converter(SubmissionStageSlugConverter, "stage") + urlpatterns = [ path("", base.edadmin, name="edadmin"), + path( + "<stage:stage>", + base._hx_submissions_in_stage, + name="_hx_submissions_in_stage", + ), path("incoming/", include("edadmin.urls.incoming")), ] diff --git a/scipost_django/edadmin/views/base.py b/scipost_django/edadmin/views/base.py index 8e8e537f42a7d0c6437aeafa5789f90c04474a90..43ca9ccf879b385bc1dca135727e6ff889fe7ff1 100644 --- a/scipost_django/edadmin/views/base.py +++ b/scipost_django/edadmin/views/base.py @@ -2,12 +2,16 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" +import operator + from django.contrib.auth.decorators import login_required, user_passes_test +from django.http import Http404 from django.shortcuts import render from guardian.shortcuts import get_objects_for_user from colleges.permissions import is_edadmin +from submissions.models import Submission @login_required @@ -16,6 +20,20 @@ def edadmin(request): """ Editorial administration page. """ - submissions = get_objects_for_user(request.user, "submissions.take_edadmin_actions") - context = { "preassignment": submissions.preassignment() } + context = { "stages": Submission.STAGE_SLUGS } return render(request, "edadmin/edadmin.html", context) + + +@login_required +@user_passes_test(is_edadmin) +def _hx_submissions_in_stage(request, stage): + """ + List Submissions in a given stage. + """ + if stage not in Submission.STAGE_SLUGS: + raise Http404(f"This Submission stage does not exist: {stage}") + submissions = get_objects_for_user(request.user, "submissions.take_edadmin_actions") + context = { + "submissions": operator.attrgetter(f"in_stage_{stage}")(submissions)(), + } + return render(request, "edadmin/_hx_submissions_list.html", context) diff --git a/scipost_django/submissions/models/submission.py b/scipost_django/submissions/models/submission.py index d5149b38385518e547dacb2ddec899b9cbb1057a..4fb89212d15b6a1fe123b2c57e712db7eb8d4b12 100644 --- a/scipost_django/submissions/models/submission.py +++ b/scipost_django/submissions/models/submission.py @@ -117,13 +117,24 @@ class Submission(models.Model): ACCEPTED_IN_ALTERNATIVE_AWAITING_PUBOFFER_ACCEPTANCE, ) + STAGE_SLUGS = ( # for converters + "incoming", + "preassignment", + "assignment", + "refereeing_in_preparation", + "in_refereeing", + "decisionmaking", + "in_production", + ) + # Further handy sets STAGE_INCOMING = (INCOMING, ADMISSIBLE) - STAGE_PREASSIGNMENT = (PREASSIGNMENT, PREASSIGNMENT_FAILED) - STAGE_ASSIGNMENT = (SEEKING_ASSIGNMENT, ASSIGNMENT_FAILED) + STAGE_PREASSIGNMENT = (PREASSIGNMENT,) + STAGE_ASSIGNMENT = (SEEKING_ASSIGNMENT,) STAGE_REFEREEING_IN_PREPARATION = (REFEREEING_IN_PREPARATION,) - STAGE_IN_REFEREEING = (IN_REFEREEING, REFEREEING_CLOSED) + STAGE_IN_REFEREEING = (IN_REFEREEING,) STAGE_DECISIONMAKING = ( + REFEREEING_CLOSED, VOTING_IN_PREPARATION, IN_VOTING, AWAITING_DECISION,