diff --git a/scipost_django/production/migrations/0009_productionstream_on_hold.py b/scipost_django/production/migrations/0009_productionstream_on_hold.py new file mode 100644 index 0000000000000000000000000000000000000000..98f305700fa57316faceebbfb77285d0062871a2 --- /dev/null +++ b/scipost_django/production/migrations/0009_productionstream_on_hold.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.18 on 2023-08-29 13:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('production', '0008_alter_productionstream_status'), + ] + + operations = [ + migrations.AddField( + model_name='productionstream', + name='on_hold', + field=models.BooleanField(default=False), + ), + ] diff --git a/scipost_django/production/models.py b/scipost_django/production/models.py index 2f36ed8cd9842e8305bae0e6d01aa0906078789c..98395469224914d4e3f747efdba665bc2dc4f200 100644 --- a/scipost_django/production/models.py +++ b/scipost_django/production/models.py @@ -101,6 +101,8 @@ class ProductionStream(models.Model): related_name="invitations_officer_streams", ) + on_hold = models.BooleanField(default=False) + work_logs = GenericRelation(WorkLog, related_query_name="streams") objects = ProductionStreamQuerySet.as_manager() @@ -131,7 +133,7 @@ class ProductionStream(models.Model): @cached_property def in_stasis(self): - return ( + return self.on_hold or ( self.submission.editorial_decision.status == EditorialDecision.AWAITING_PUBOFFER_ACCEPTANCE ) diff --git a/scipost_django/production/templates/production/_hx_productionstream_details_contents.html b/scipost_django/production/templates/production/_hx_productionstream_details_contents.html index 63294a87c8cc3f41a0856bab34bb0fc8cba04286..b6a627a66513e8269f05afa48f135652d329504d 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_details_contents.html +++ b/scipost_django/production/templates/production/_hx_productionstream_details_contents.html @@ -167,23 +167,21 @@ </div> - {% if perms.scipost.can_draft_publication or perms.scipost.can_publish_accepted_submission %} <div class="mb-2 mb-md-0 mt-md-auto px-2"> - <div class="row mb-0 mt-2 g-2"> - {% if perms.scipost.can_publish_accepted_submission %} + <div class="row mb-0 mt-2 g-2"> + {% if "can_work_for_stream" in sub_perms and perms.scipost.can_assign_production_officer %} <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty"> <div class="row m-0 d-none-empty"> - <button class="btn btn-warning text-white" - hx-get="{% url 'production:_hx_mark_as_completed' stream_id=productionstream.id %}" - {% if productionstream.status != 'published' %}hx-confirm="Are you sure you want to mark this unpublished stream as completed?"{% endif %} - hx-target="#productionstream-{{ productionstream.id }}-details"> - Mark this stream as completed - </button> + <a class="btn btn-warning text-white" role="button" + hx-get="{% url 'production:_hx_toggle_on_hold' stream_id=productionstream.id %}" + hx-target="#productionstream-{{productionstream.id}}-details" + hx-confirm="Are you sure you wish to put this stream on hold?" + hx-swap="outerHTML">Put stream on hold</a> </div> </div> {% endif %} - + {% if perms.scipost.can_draft_publication and productionstream.status == 'accepted' %} <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty"> <div class="row m-0 d-none-empty"> @@ -194,10 +192,22 @@ </div> </div> {% endif %} + + {% if perms.scipost.can_publish_accepted_submission %} + <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty"> + <div class="row m-0 d-none-empty"> + <a class="btn btn-warning text-white" role="button" + hx-get="{% url 'production:_hx_mark_as_completed' stream_id=productionstream.id %}" + {% if productionstream.status != 'published' %}hx-confirm="Are you sure you want to mark this unpublished stream as completed?"{% endif %} + hx-target="#productionstream-{{ productionstream.id }}-details"> + Mark this stream as completed + </a> + </div> + </div> + {% endif %} </div> </div> - {% endif %} {% endif %} </div> diff --git a/scipost_django/production/templates/production/_hx_productionstream_summary_assignees_status.html b/scipost_django/production/templates/production/_hx_productionstream_summary_assignees_status.html index 96a9c7fe7a4a1e39d36b08259ad60394add6261a..12984e28bde53a8caa9aca84f63b39583e2ad891 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_summary_assignees_status.html +++ b/scipost_django/production/templates/production/_hx_productionstream_summary_assignees_status.html @@ -43,9 +43,20 @@ <div class="row mb-0 justify-content-between align-items-center"> <small class="col text-muted text-nowrap">Stream Status</small> <div class="col-auto"> - <div class="p-2 badge bg-{% if productionstream.status == 'initiated' %}danger{% else %}primary{% endif %}"> - {{ productionstream.status|readable_str|title }} - </div> + {% if productionstream.on_hold %} + <div class="p-2 badge bg-warning pe-auto" + title="Click to remove from 'On Hold'" + hx-get="{% url 'production:_hx_toggle_on_hold' stream_id=productionstream.id %}" + hx-target="#productionstream-{{productionstream.id}}-details" + hx-swap="outerHTML" hx-confirm="Are you sure the issues in this stream have been resolved?"> + <span class="text-white justify-self-start">{% include 'bi/exclamation-triangle-fill.html' %}</span> + On Hold + </div> + {% else %} + <div class="p-2 badge bg-{% if productionstream.status == 'initiated' %}danger{% else %}primary{% endif %}"> + {{ productionstream.status|readable_str|title }} + </div> + {% endif %} </div> </div> </div> diff --git a/scipost_django/production/urls.py b/scipost_django/production/urls.py index 54b32e500a26161a0ccefe456f6d2454c9d2f932..691e16c4f58c0627feaee19a18c14b979e3861c9 100644 --- a/scipost_django/production/urls.py +++ b/scipost_django/production/urls.py @@ -279,6 +279,11 @@ urlpatterns = [ production_views._hx_mark_as_completed, name="_hx_mark_as_completed", ), + path( + "_hx_toggle_on_hold", + production_views._hx_toggle_on_hold, + name="_hx_toggle_on_hold", + ), path( "mark_completed", production_views.mark_as_completed, diff --git a/scipost_django/production/views.py b/scipost_django/production/views.py index a3b7189d35e12a46768e5b5cebc6a01043090303..8a4e7e4d6ac27cf989aa49ce5e26aee363d95cc9 100644 --- a/scipost_django/production/views.py +++ b/scipost_django/production/views.py @@ -1024,6 +1024,53 @@ def _hx_mark_as_completed(request, stream_id): ) +@is_production_user() +@permission_required("scipost.can_assign_production_officer", raise_exception=True) +@transaction.atomic +def _hx_toggle_on_hold(request, stream_id): + productionstream = get_object_or_404( + ProductionStream.objects.ongoing(), pk=stream_id + ) + + checker = ObjectPermissionChecker(request.user) + if not checker.has_perm("can_work_for_stream", productionstream): + return HTMXPermissionsDenied("You cannot work in this stream.") + + productionstream.on_hold = not productionstream.on_hold + productionstream.save() + + if productionstream.on_hold: + production_event = ProductionEvent( + stream=productionstream, + event="status", + comments=" marked the Production Stream as on hold.", + noted_by=request.user.production_user, + ) + messages.success( + request, + "Production Stream has been marked as on hold.", + ) + else: + production_event = ProductionEvent( + stream=productionstream, + event="status", + comments=" unmarked the Production Stream as on hold.", + noted_by=request.user.production_user, + ) + messages.success( + request, + "Production Stream has been unmarked as on hold.", + ) + + production_event.save() + + return render( + request, + "production/_hx_productionstream_details.html", + {"productionstream": productionstream}, + ) + + @is_production_user() @permission_required("scipost.can_publish_accepted_submission", raise_exception=True) @transaction.atomic