From acd1fd1d38e9aeaa4ff4620bba48627e180c81a9 Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Thu, 8 Jun 2023 16:48:56 +0200 Subject: [PATCH] add auto explansion of accordion submenu change load for intersect --- ...ctionstream_actions_change_properties.html | 40 -------------- ..._productionstream_actions_proofs_item.html | 3 +- ..._hx_productionstream_details_contents.html | 55 +++++++++---------- ...uctionstream_details_summary_contents.html | 26 ++++----- .../templates/production/upload_proofs.html | 4 +- scipost_django/production/views.py | 29 ++++++++-- 6 files changed, 69 insertions(+), 88 deletions(-) diff --git a/scipost_django/production/templates/production/_hx_productionstream_actions_change_properties.html b/scipost_django/production/templates/production/_hx_productionstream_actions_change_properties.html index 2062f3fdf..7afb65a41 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_actions_change_properties.html +++ b/scipost_django/production/templates/production/_hx_productionstream_actions_change_properties.html @@ -1,46 +1,6 @@ {% load bootstrap %} {% load scipost_extras %} -{% comment %} {% if status_form|all_fields_have_choices %} - <form id="productionstream-{{ productionstream.id }}-update-status" hx-post="{% url 'production:update_status' productionstream.id %}" hx-target="this" hx-swap="outerHTML" hx-trigger="submit"> - {% csrf_token %} - <div class="row"> - <div class="col">{{ status_form|bootstrap_purely_inline }}</div> - <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty" hx-post="{% url 'production:render_action_buttons' productionstream.id 'status' %}" hx-swap="innerHTML" hx-trigger="load, change from:select#productionstream_{{ productionstream.id }}_id_status" hx-target="this"></div> - </div> - </form> -{% endif %} - -{% if supervisor_form|all_fields_have_choices %} - <form id="productionstream-{{ productionstream.id }}-update-supervisor" hx-post="{% url 'production:update_supervisor' productionstream.id %}" hx-target="this" hx-swap="outerHTML" hx-trigger="submit"> - {% csrf_token %} - <div class="row"> - <div class="col">{{ supervisor_form|bootstrap_purely_inline }}</div> - <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty" hx-post="{% url 'production:render_action_buttons' productionstream.id 'supervisor' %}" hx-swap="innerHTML" hx-trigger="load, change from:select#productionstream_{{ productionstream.id }}_id_supervisor" hx-target="this"></div> - </div> - </form> -{% endif %} - -{% if officer_form|all_fields_have_choices %} - <form id="productionstream-{{ productionstream.id }}-update-officer" hx-post="{% url 'production:update_officer' productionstream.id %}" hx-target="this" hx-swap="outerHTML" hx-trigger="submit"> - {% csrf_token %} - <div class="row"> - <div class="col">{{ officer_form|bootstrap_purely_inline }}</div> - <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty" hx-post="{% url 'production:render_action_buttons' productionstream.id 'officer' %}" hx-swap="innerHTML" hx-trigger="load, change from:select#productionstream_{{ productionstream.id }}_id_officer" hx-target="this"></div> - </div> - </form> -{% endif %} - -{% if invitations_officer_form|all_fields_have_choices %} - <form id="productionstream-{{ productionstream.id }}-update-invitations_officer" hx-post="{% url 'production:update_invitations_officer' productionstream.id %}" hx-target="this" hx-swap="outerHTML" hx-trigger="submit"> - {% csrf_token %} - <div class="row"> - <div class="col">{{ invitations_officer_form|bootstrap_purely_inline }}</div> - <div class="col-12 col-sm-auto col-md-12 col-lg-auto h-100 d-none-empty" hx-post="{% url 'production:render_action_buttons' productionstream.id 'invitations_officer' %}" hx-swap="innerHTML" hx-trigger="load, change from:select#productionstream_{{ productionstream.id }}_id_invitations_officer" hx-target="this"></div> - </div> - </form> -{% endif %} {% endcomment %} - {% include "production/_hx_productionstream_change_status.html" with form=status_form stream=productionstream %} {% include "production/_hx_productionstream_change_supervisor.html" with form=supervisor_form stream=productionstream %} {% include "production/_hx_productionstream_change_officer.html" with form=officer_form stream=productionstream %} diff --git a/scipost_django/production/templates/production/_hx_productionstream_actions_proofs_item.html b/scipost_django/production/templates/production/_hx_productionstream_actions_proofs_item.html index af0f23f13..6848c94ea 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_actions_proofs_item.html +++ b/scipost_django/production/templates/production/_hx_productionstream_actions_proofs_item.html @@ -33,7 +33,8 @@ <div id="productionstream-{{ stream.id }}-proofs-list-accordion-proofs-{{ proofs.version }}-action-row" class="row g-2"> <div class="col-12 col-sm-6 col-md-12 col-lg-6 h-100 d-none-empty"> - <a class="row m-0 d-none-empty" + <a download + class="row m-0 d-none-empty" href="{% url 'production:proofs_pdf' proofs.slug %}"> <button class="btn btn-sm btn-secondary">Download Proofs</button> </a> 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 97f801c2e..4d58bc797 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_details_contents.html +++ b/scipost_django/production/templates/production/_hx_productionstream_details_contents.html @@ -18,25 +18,25 @@ {% if perms.scipost.can_take_decisions_related_to_proofs %} <div class="accordion-item"> <h2 class="accordion-header" - id="productionstream-{{ productionstream.id }}-change-stream-properties-header"> - <button class="accordion-button fs-6 collapsed" + id="productionstream-{{ productionstream.id }}-change-properties-header"> + <button class="accordion-button fs-6 {% if accordion_default_open == '' or accordion_default_open != 'change-properties' %}collapsed{% endif %}" type="button" data-bs-toggle="collapse" - data-bs-target="#productionstream-{{ productionstream.id }}-change-stream-properties" + data-bs-target="#productionstream-{{ productionstream.id }}-change-properties" aria-expanded="true" - aria-controls="productionstream-{{ productionstream.id }}-change-stream-properties" - hx-get="{% url 'production:_hx_productionstream_actions_change_properties' productionstream_id=productionstream.id %}" - hx-trigger="click once, submit from:#productionstream-{{ productionstream.id }}-details-contents target:form delay:1000" - hx-target="#productionstream-{{ productionstream.id }}-change-stream-properties-body"> - Change stream properties + aria-controls="productionstream-{{ productionstream.id }}-change-properties"> + Change Properties </button> </h2> - <div id="productionstream-{{ productionstream.id }}-change-stream-properties" - class="accordion-collapse collapse" - aria-labelledby="productionstream-{{ productionstream.id }}-change-stream-properties-header" + <div id="productionstream-{{ productionstream.id }}-change-properties" + class="accordion-collapse collapse {% if accordion_default_open == 'change-properties' %}show{% endif %}" + aria-labelledby="productionstream-{{ productionstream.id }}-change-properties-header" data-bs-parent="#productionstream-{{ productionstream.id }}-actions-accordion"> <div class="accordion-body"> - <div id="productionstream-{{ productionstream.id }}-change-stream-properties-body"> + <div id="productionstream-{{ productionstream.id }}-change-properties-body" + class="accordion-body" + hx-get="{% url 'production:_hx_productionstream_actions_change_properties' productionstream_id=productionstream.id %}" + hx-trigger="intersect once, submit from:#productionstream-{{ productionstream.id }}-details-contents target:form delay:1000"> {% comment %} Placeholder before HTMX content loads {% endcomment %} <div class="placeholder-glow"> @@ -67,22 +67,21 @@ <div class="accordion-item"> <h2 class="accordion-header" id="productionstream-{{ productionstream.id }}-upload-proofs-header"> - <button class="accordion-button fs-6 collapsed" + <button class="accordion-button fs-6 {% if accordion_default_open == '' or accordion_default_open != 'upload_proofs' %}collapsed{% endif %}" type="button" data-bs-toggle="collapse" data-bs-target="#productionstream-{{ productionstream.id }}-upload-proofs" aria-expanded="false" - aria-controls="productionstream-{{ productionstream.id }}-upload-proofs" - hx-get="{% url 'production:upload_proofs' stream_id=productionstream.id %}" - hx-trigger="click once" - hx-target="#productionstream-{{ productionstream.id }}-upload-proofs-body">Upload Proofs</button> + aria-controls="productionstream-{{ productionstream.id }}-upload-proofs">Upload Proofs</button> </h2> <div id="productionstream-{{ productionstream.id }}-upload-proofs" - class="accordion-collapse collapse" + class="accordion-collapse collapse {% if accordion_default_open == 'upload-proofs' %}show{% endif %}" aria-labelledby="productionstream-{{ productionstream.id }}-upload-proofs-header" data-bs-parent="#productionstream-{{ productionstream.id }}-actions-accordion"> <div id="productionstream-{{ productionstream.id }}-upload-proofs-body" - class="accordion-body"> + class="accordion-body" + hx-get="{% url 'production:upload_proofs' stream_id=productionstream.id %}" + hx-trigger="intersect once"> {% comment %} Placeholder before HTMX content loads {% endcomment %} <div class="placeholder-glow"> @@ -111,23 +110,21 @@ <div class="accordion-item"> <h2 class="accordion-header" id="productionstream-{{ productionstream.id }}-work-log-header"> - <button class="accordion-button fs-6 collapsed" + <button class="accordion-button fs-6 {% if accordion_default_open == '' or accordion_default_open != 'work-log' %}collapsed{% endif %}" type="button" data-bs-toggle="collapse" data-bs-target="#productionstream-{{ productionstream.id }}-work-log" aria-expanded="false" - aria-controls="productionstream-{{ productionstream.id }}-work-log" - hx-get="{% url 'production:_hx_productionstream_actions_work_log' productionstream_id=productionstream.id %}" - hx-trigger="click once, htmx:trigger from:#productionstream-{{ productionstream.id }}-work-log-body target:a.work_log_delete_btn delay:1000" - hx-target="#productionstream-{{ productionstream.id }}-work-log-body" - hx-swap="innerHTML">Work Log</button> + aria-controls="productionstream-{{ productionstream.id }}-work-log">Work Log</button> </h2> <div id="productionstream-{{ productionstream.id }}-work-log" - class="accordion-collapse collapse" + class="accordion-collapse collapse {% if accordion_default_open == 'work-log' %}show{% endif %}" aria-labelledby="productionstream-{{ productionstream.id }}-work-log-header" data-bs-parent="#productionstream-{{ productionstream.id }}-actions-accordion"> <div id="productionstream-{{ productionstream.id }}-work-log-body" - class="accordion-body"> + class="accordion-body" + hx-get="{% url 'production:_hx_productionstream_actions_work_log' productionstream_id=productionstream.id %}" + hx-trigger="intersect once, htmx:trigger from:this target:a.work_log_delete_btn delay:1000"> {% comment %} Placeholder before HTMX content loads {% endcomment %} <div class="placeholder-glow"> @@ -184,7 +181,7 @@ <div class="row m-0 d-none-empty"> <button class="btn btn-warning text-white" hx-get="{% url 'production:mark_as_completed' stream_id=productionstream.id %}" - hx-confim="Are you sure you want to mark this stream as completed?" + {% if stream.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> @@ -217,7 +214,7 @@ class="overflow-scroll mb-4" style="max-height: max(50vh, 40em)" hx-get="{% url 'production:render_stream_events' productionstream.id %}" - hx-trigger="load, submit from:#productionstream-{{ productionstream.id }}-details target:form delay:500, click from:#productionstream-{{ productionstream.id }}-details target:.proof-action-button delay:500"> + hx-trigger="intersect once, submit from:#productionstream-{{ productionstream.id }}-details target:form delay:500, click from:#productionstream-{{ productionstream.id }}-details target:.proof-action-button delay:500"> {% comment %} Placeholder before HTMX content loads {% endcomment %} <table class="table table-bordered table-striped overflow-scroll mb-0" diff --git a/scipost_django/production/templates/production/_productionstream_details_summary_contents.html b/scipost_django/production/templates/production/_productionstream_details_summary_contents.html index 20d76cf19..a6ee8f1f9 100644 --- a/scipost_django/production/templates/production/_productionstream_details_summary_contents.html +++ b/scipost_django/production/templates/production/_productionstream_details_summary_contents.html @@ -53,48 +53,48 @@ <div id="productionstream-{{ productionstream.id }}-summary-assignees" class="col-md-6" hx-get="{% url 'production:render_stream_assignees_status' productionstream.id %}" - hx-trigger="intersect, submit from:#productionstream-{{ productionstream.id }}-details target:form delay:500, click from:#productionstream-{{ productionstream.id }}-details target:.proof-action-button delay:500"> + hx-trigger="intersect once, submit from:#productionstream-{{ productionstream.id }}-details target:form delay:500, click from:#productionstream-{{ productionstream.id }}-details target:.proof-action-button delay:500"> {% comment %} Placeholder while HTMX is loading {% endcomment %} <div class="row mb-0 placeholder-glow"> <div class="order-3 order-sm-1 order-md-3 order-xl-1 col-sm-6 col-md-12 col-xl-6"> <div class="row justify-content-between"> - <small class="col-4 text-muted text-nowrap placeholder">Stream opened</small> + <small class="col-4 text-muted text-nowrap">Stream opened</small> <div class="col-8"> - <div class="w-100 placeholder"></div> + <div class="ms-2 w-100 placeholder"></div> </div> </div> </div> <div class="order-2 order-sm-4 order-md-2 order-xl-4 col-sm-6 col-md-12 col-xl-6"> <div class="row justify-content-between"> - <small class="col-4 text-muted text-nowrap placeholder">Officer</small> + <small class="col-4 text-muted text-nowrap">Officer</small> <div class="col-8 text-nowrap text-truncate"> - <div class="w-100 placeholder"></div> + <div class="ms-2 w-100 placeholder"></div> </div> </div> </div> <div class="order-4 order-sm-3 order-md-4 order-xl-3 col-sm-6 col-md-12 col-xl-6"> <div class="row justify-content-between"> - <small class="col-4 text-muted text-nowrap placeholder">Latest activity</small> + <small class="col-4 text-muted text-nowrap">Latest activity</small> <div class="col-8"> - <div class="w-100 placeholder"></div> + <div class="ms-2 w-100 placeholder"></div> </div> </div> </div> <div class="order-1 order-sm-2 order-md-1 order-xl-2 col-sm-6 col-md-12 col-xl-6"> <div class="row justify-content-between"> - <small class="col-4 text-muted text-nowrap placeholder">Supervisor</small> + <small class="col-4 text-muted text-nowrap">Supervisor</small> <div class="col-8 text-nowrap text-truncate"> - <div class="w-100 placeholder"></div> + <div class="ms-2 w-100 placeholder"></div> </div> </div> </div> <div class="order-5 order-sm-5 order-md-5 order-xl-5 col-sm-6 col-md-12 col-xl-6"> <div class="row mb-0 justify-content-between align-items-center"> - <small class="col-4 text-muted text-nowrap placeholder">Stream Status</small> - <div class="col-8"> - <div class="badge bg-secondary w-50"> - <div class="w-100 placeholder"></div> + <small class="col-4 text-muted text-nowrap">Stream Status</small> + <div class="offset-5 col-3"> + <div class="badge bg-primary w-100"> + <div class="placeholder py-2"></div> </div> </div> </div> diff --git a/scipost_django/production/templates/production/upload_proofs.html b/scipost_django/production/templates/production/upload_proofs.html index a1ba1307b..afa710d9b 100644 --- a/scipost_django/production/templates/production/upload_proofs.html +++ b/scipost_django/production/templates/production/upload_proofs.html @@ -13,7 +13,9 @@ <div class="row mt-3"> <div class="col-12"> - <form method="post" enctype="multipart/form-data"> + <form enctype="multipart/form-data" + hx-post="{% url 'production:upload_proofs' stream_id=stream.id %}" + hx-target="#productionstream-{{ stream.id }}-upload-proofs-body"> {% csrf_token %} {{ form|bootstrap_purely_inline }} <input type="submit" diff --git a/scipost_django/production/views.py b/scipost_django/production/views.py index ae47ae093..7f7c7631a 100644 --- a/scipost_django/production/views.py +++ b/scipost_django/production/views.py @@ -106,6 +106,25 @@ def _hx_productionstream_details_contents(request, productionstream_id): upload_proofs_form = ProofsUploadForm() + # Determine which accordion tab to open by default + accordion_default_open = "" + if request.user.production_user == productionstream.supervisor: + if productionstream.status in [ + constants.PROOFS_ACCEPTED, + ]: + accordion_default_open = "upload-proofs" + else: + accordion_default_open = "change-properties" + + if request.user.production_user == productionstream.officer: + if not productionstream.work_logs.all(): + accordion_default_open = "work-log" + elif not productionstream.proofs.all(): + accordion_default_open = "upload-proofs" + + if productionstream.status == constants.PRODUCTION_STREAM_INITIATED: + accordion_default_open = "change-properties" + context = { "productionstream": productionstream, "status_form": status_form, @@ -113,6 +132,7 @@ def _hx_productionstream_details_contents(request, productionstream_id): "inv_officer_form": inv_officer_form, "prod_officer_form": prod_officer_form, "upload_proofs_form": upload_proofs_form, + "accordion_default_open": accordion_default_open, } return render( request, @@ -405,7 +425,6 @@ def _hx_productionstream_actions_work_log(request, productionstream_id): log.content = productionstream log.user = request.user log.save() - messages.success(request, "Work Log added to Stream.") else: # messages.warning(request, "The form was invalidly filled.") pass @@ -979,7 +998,11 @@ def upload_proofs(request, stream_id): stream = get_object_or_404(ProductionStream.objects.ongoing(), pk=stream_id) checker = ObjectPermissionChecker(request.user) if not checker.has_perm("can_work_for_stream", stream): - return redirect(reverse("production:production")) + return HttpResponse( + r"""<div class="text-danger border border-danger p-3"> + You are forbidden from working in this stream. + </div>""" + ) form = ProofsUploadForm(request.POST or None, request.FILES or None) if form.is_valid(): @@ -990,7 +1013,6 @@ def upload_proofs(request, stream_id): Proofs.objects.filter(stream=stream).exclude(version=proofs.version).exclude( status=constants.PROOFS_ACCEPTED ).update(status=constants.PROOFS_RENEWED) - messages.success(request, "Proof uploaded.") # Update Stream status if stream.status == constants.PROOFS_TASKED: @@ -1007,7 +1029,6 @@ def upload_proofs(request, stream_id): noted_by=request.user.production_user, ) prodevent.save() - return redirect(stream.get_absolute_url()) context = {"stream": stream, "form": form, "total_proofs": stream.proofs.count()} return render(request, "production/upload_proofs.html", context) -- GitLab