diff --git a/scipost_django/tasks/tasks/task_kinds.py b/scipost_django/tasks/tasks/task_kinds.py index ba79a922ed8d25d1fc42a0643ec33d27a1b960df..3f6a40a8cc7595c40bbce014df6cb75c21cf9f59 100644 --- a/scipost_django/tasks/tasks/task_kinds.py +++ b/scipost_django/tasks/tasks/task_kinds.py @@ -16,7 +16,12 @@ from django.db.models import ( from django.db.models.functions import Cast, Coalesce from django.urls import reverse_lazy from django.utils import timezone -from scipost.templatetags.user_groups import is_financial_admin +from scipost.templatetags.user_groups import ( + is_active_fellow, + is_ed_admin, + is_financial_admin, +) +from guardian.shortcuts import get_objects_for_user from tasks.tasks.task import TaskKind from tasks.tasks.task_action import ViewAction @@ -41,6 +46,11 @@ def get_all_task_kinds(user: "User | None" = None) -> Collection[type[TaskKind]] return classes +########################## +## Financial Admin Tasks +########################## + + class ScheduleSubsidyPayments(TaskKind): name = "Schedule Subsidy Payments" task_title = "Schedule Payments for {object}" @@ -207,3 +217,149 @@ class CheckSubsidyPaymentTask(TaskKind): ) .filter(Q(status=SUBSIDY_INVOICED)) ) + + +##################### +## Fellow Tasks +##################### + + +class TreatOngoingAssignmentsTask(TaskKind): + name = "Treat Ongoing Assignments" + task_title = "{object}" + description = "Continue your work for your ongoing editorial assignments." + template_name = "tasks/kinds/editorial_assignment.html" + actions = [ + lambda task: ViewAction( + url=reverse_lazy( + "submissions:editorial_page", + kwargs={ + "identifier_w_vn_nr": task.data[ + "object" + ].submission.preprint.identifier_w_vn_nr + }, + ), + content="Editorial page", + ), + ] + + @staticmethod + def is_user_eligible(user): + return is_active_fellow(user) if user is not None else False + + @classmethod + def get_queryset(cls) -> "QuerySet": + from submissions.models.assignment import EditorialAssignment + + if cls.user is None: + return EditorialAssignment.objects.none() + + return ( + EditorialAssignment.objects.ongoing() + .filter(to=cls.user.contributor) + .prefetch_related("submission") + ) + + +class VetCommentTask(TaskKind): + name = "Vet Comment" + task_title = "Vet {object}" + description = "Vet a comment that has been submitted for approval." + actions = [ + lambda task: ViewAction( + url=reverse_lazy( + "comments:vet_submitted_comment", + kwargs={"comment_id": task.data["object"].pk}, + ), + content="Vet", + ), + ] + + @staticmethod + def is_user_eligible(user): + return ( + is_active_fellow(user) or is_ed_admin(user) if user is not None else False + ) + + @classmethod + def get_queryset(cls) -> "QuerySet": + return get_objects_for_user( + cls.user, "comments.can_vet_comments" + ).awaiting_vetting() + + +class VetReportTask(TaskKind): + name = "Vet Report" + task_title = "Vet {object}" + description = "Vet a report that has been submitted for approval." + actions = [ + lambda task: ViewAction( + url=reverse_lazy( + "submissions:vet_submitted_report", + kwargs={"report_id": task.data["object"].pk}, + ), + content="Vet", + ), + ] + + @staticmethod + def is_user_eligible(user): + return ( + is_active_fellow(user) + or is_ed_admin(user) + or user.has_perm("scipost.can_vet_submitted_reports") + if user is not None + else False + ) + + @classmethod + def get_queryset(cls) -> "QuerySet": + from submissions.models.report import Report + from submissions.models.submission import Submission + + if cls.user is None: + return Report.objects.none() + + if cls.user.has_perm("scipost.can_vet_submitted_reports"): + return Report.objects.awaiting_vetting() + + return Report.objects.filter( + submission__in=Submission.objects.in_pool_filter_for_eic( + cls.user, latest=False, historical=True + ) + ).awaiting_vetting() + + +class SelectRefereeingCycleTask(TaskKind): + name = "Select Refereeing Cycle" + task_title = "Select Refereeing Cycle for {object}" + description = "Select the refereeing cycle for a submission." + actions = [ + lambda task: ViewAction( + url=reverse_lazy( + "submissions:editorial_page", + kwargs={ + "identifier_w_vn_nr": task.data[ + "object" + ].preprint.identifier_w_vn_nr + }, + ), + content="Editorial page", + ), + ] + + @staticmethod + def is_user_eligible(user): + return is_active_fellow(user) if user is not None else False + + @classmethod + def get_queryset(cls) -> "QuerySet": + from submissions.models.submission import Submission + + if cls.user is None: + return Submission.objects.none() + + return Submission.objects.filter( + editor_in_charge=cls.user.contributor, + refereeing_cycle__isnull=True, + ) diff --git a/scipost_django/tasks/templates/tasks/kinds/editorial_assignment.html b/scipost_django/tasks/templates/tasks/kinds/editorial_assignment.html new file mode 100644 index 0000000000000000000000000000000000000000..b5137d05b1c75486c84b1d04af5ef8794444d322 --- /dev/null +++ b/scipost_django/tasks/templates/tasks/kinds/editorial_assignment.html @@ -0,0 +1,36 @@ +<div class="d-flex"> + <div class="flex-grow-1"> + <h3 class="fs-5">{{ task.data.object.submission.title }}</h3> + <span>by {{ task.data.object.submission.author_list|truncatechars:150 }}</span> + + </div> + + <div class="btn-group" + role="group" + aria-label="Button group with nested dropdown"> + + {% for action in task.actions|slice:":2" %}{{ action.as_html|safe }}{% endfor %} + + + {% if task.actions|length > 2 %} + <div class="btn-group" role="group"> + <button class="btn btn-sm btn-light dropdown-toggle" + type="button" + data-bs-toggle="dropdown" + aria-expanded="false"> + <span>More</span> + </button> + <ul class="dropdown-menu dropdown-menu-end"> + + {% for action in task.actions|slice:"2:" %} + <li class="dropdown-item">{{ action.element|safe }}</li> + {% endfor %} + + + </ul> + </div> + {% endif %} + + </div> + +</div>