diff --git a/scipost_django/finances/templates/finances/_logs.html b/scipost_django/finances/templates/finances/_logs.html index 057d87f8802bff604c3596eb552e3a5c2b9183ab..e5576bb250c9cf78f28dab580cf4ccaadc491e52 100644 --- a/scipost_django/finances/templates/finances/_logs.html +++ b/scipost_django/finances/templates/finances/_logs.html @@ -1,27 +1,38 @@ {% load scipost_extras %} -{% for log in logs %} - <div id="log_{{ log.slug }}" class="row"> - <div class="col"> - <strong>{{ log.user.first_name }} {{ log.user.last_name }}</strong> - <br> - <span class="text-muted">{{ log.log_type }}</span> - <br> - {{ log.comments|linebreaksbr }} - </div> - <div class="text-muted text-end col-auto d-flex"> - <div class=""> - {{ log.work_date }} +<div class="container"> + {% for log in logs %} + <div id="log_{{ log.slug }}" class="row"> + <div class="col"> + <strong>{{ log.user.first_name }} {{ log.user.last_name }}</strong> + <br> + <span class="text-muted">{{ log.log_type }}</span> <br> - <strong>Duration: {{ log.duration|duration }}</strong> + {{ log.comments|linebreaksbr }} </div> - <div class="ps-2"> - <a class="text-danger" href="{% url 'finances:log_delete' log.slug %}"><span aria-hidden="true"> - {% include 'bi/trash-fill.html' %} - </a> + <div class="text-muted text-end col-auto d-flex"> + <div class=""> + {{ log.work_date }} + <br> + <strong>Duration: {{ log.duration|duration }}</strong> + </div> + <div class="ps-2"> + {% if log.user == request.user %} + <a id="log_{{ log.slug }}_delete_btn" + class="text-danger work_log_delete_btn" + hx-get="{% url 'finances:log_delete' log.slug %}" + hx-target="#log_{{ log.slug }}" + hx-confirm="Delete this log?"> + <span aria-hidden="true">{% include 'bi/trash-fill.html' %}</span> + </a> + {% else %} + <span class="opacity-0">{% include 'bi/trash-fill.html' %}</span> + {% endif %} + </div> + </div> </div> - </div> -{% empty %} - No logs were found. -{% endfor %} + {% empty %} + <div>No logs were found.</div> + {% endfor %} +</div> diff --git a/scipost_django/finances/urls.py b/scipost_django/finances/urls.py index 0e76d34e052a3a05441546c3ed583c836cf000d6..783ef311b17acc9322ee59ff7850d16c815c7c15 100644 --- a/scipost_django/finances/urls.py +++ b/scipost_django/finances/urls.py @@ -122,7 +122,7 @@ urlpatterns = [ # Timesheets path("timesheets", views.timesheets, name="timesheets"), path("timesheets/detailed", views.timesheets_detailed, name="timesheets_detailed"), - path("logs/<slug:slug>/delete", views.LogDeleteView.as_view(), name="log_delete"), + path("logs/<slug:slug>/delete", views._hx_worklog_delete, name="log_delete"), # PeriodicReports path("periodicreport/<int:pk>/file", views.periodicreport_file, name="periodicreport_file"), ] diff --git a/scipost_django/finances/views.py b/scipost_django/finances/views.py index d91c6e0ec37f0e676af4bb416584dc8dbb600b78..cbd3b2bc23eac7cb148b4e2272f9b1d2eceb32ac 100644 --- a/scipost_django/finances/views.py +++ b/scipost_django/finances/views.py @@ -551,6 +551,18 @@ class LogDeleteView(LoginRequiredMixin, DeleteView): return self.object.content.get_absolute_url() +@permission_required("scipost.can_view_production", raise_exception=True) +def _hx_worklog_delete(request, slug): + log = get_object_or_404(WorkLog, pk=slug_to_id(slug)) + log.delete() + + return HttpResponse( + r"""<div class="text-danger border border-danger p-3"> + Work log has been deleted. + </div>""" + ) + + ################### # PeriodicReports # ################### diff --git a/scipost_django/production/forms.py b/scipost_django/production/forms.py index cf8cfa4f8884c46d70b564a19e123887633a98ca..e8dfa0bc46d93687b8999e868041e092c453a570 100644 --- a/scipost_django/production/forms.py +++ b/scipost_django/production/forms.py @@ -71,7 +71,10 @@ class AssignOfficerForm(forms.ModelForm): def save(self, commit=True): stream = super().save(False) if commit: - if stream.status == constants.PRODUCTION_STREAM_INITIATED: + if stream.status in [ + constants.PRODUCTION_STREAM_INITIATED, + constants.PROOFS_SOURCE_REQUESTED, + ]: stream.status = constants.PROOFS_TASKED stream.save() return stream @@ -107,13 +110,15 @@ class StreamStatusForm(forms.ModelForm): def get_available_statuses(self): if self.instance.status in [ - constants.PRODUCTION_STREAM_INITIATED, constants.PRODUCTION_STREAM_COMPLETED, + constants.PROOFS_SOURCE_REQUESTED, constants.PROOFS_ACCEPTED, constants.PROOFS_CITED, ]: # No status change can be made by User return () + elif self.instance.status == constants.PRODUCTION_STREAM_INITIATED: + return ((constants.PROOFS_SOURCE_REQUESTED, "Source files requested"),) elif self.instance.status == constants.PROOFS_TASKED: return ((constants.PROOFS_PRODUCED, "Proofs have been produced"),) elif self.instance.status == constants.PROOFS_PRODUCED: @@ -125,6 +130,7 @@ class StreamStatusForm(forms.ModelForm): return ( (constants.PROOFS_SENT, "Proofs sent to Authors"), (constants.PROOFS_CORRECTED, "Corrections implemented"), + (constants.PROOFS_SOURCE_REQUESTED, "Source files requested"), ) elif self.instance.status == constants.PROOFS_SENT: return ( diff --git a/scipost_django/production/templates/production/_hx_productionstream_actions_work_log.html b/scipost_django/production/templates/production/_hx_productionstream_actions_work_log.html index 46916a2b6fae5e9416353c02c0c366ee78d22d5f..a907e867d9cb54eb5055fd54c1a6417a172a8213 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_actions_work_log.html +++ b/scipost_django/production/templates/production/_hx_productionstream_actions_work_log.html @@ -6,7 +6,7 @@ <h3 class="col">Work Logs</h3> {% include 'finances/_logs.html' with logs=productionstream.work_logs.all|dictsort:"created" %} - {% if productionstream.total_duration %} + {% if productionstream.total_duration and productionstream.work_logs.all.count > 1 %} <div class="col-auto ms-auto me-5 border-primary border-top pt-2"> Total: <strong>{{ productionstream.total_duration|duration }}</strong> </div> 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 c96ef07d7ff689535ef170b5a0d4ee80d9eab491..b078d5d6e4a224290a548c47c9ee657d6cb6128a 100644 --- a/scipost_django/production/templates/production/_hx_productionstream_details_contents.html +++ b/scipost_django/production/templates/production/_hx_productionstream_details_contents.html @@ -77,7 +77,7 @@ 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" + hx-trigger="load, 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">Work Log</button> </h2> <div id="productionstream-{{ productionstream.id }}-work-log" diff --git a/scipost_django/production/templates/production/production_new.html b/scipost_django/production/templates/production/production_new.html index d42389370378096a979bc538bd9755cc22475bae..39c92d651f17357e62ba8aa50b0c7e2c35bf4cb3 100644 --- a/scipost_django/production/templates/production/production_new.html +++ b/scipost_django/production/templates/production/production_new.html @@ -48,13 +48,6 @@ </div> </details> - <div class="row"> - - - - <div class="col-auto"></div> - - </div> <div id="search-productionstreams-results" class="mt-2"></div> {% endblock content %} diff --git a/scipost_django/scipost/templatetags/scipost_extras.py b/scipost_django/scipost/templatetags/scipost_extras.py index 1e3eca861aca659d82e32c38b431431c272752ed..76c9f30aae17c08f176e63ed53e9d6a140a85d7a 100644 --- a/scipost_django/scipost/templatetags/scipost_extras.py +++ b/scipost_django/scipost/templatetags/scipost_extras.py @@ -2,6 +2,7 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" +from functools import reduce import random from django import template @@ -97,3 +98,19 @@ def associated_contributors(draft): return Contributor.objects.filter( user__last_name__icontains=draft.last_name ).order_by("user__last_name") + + +@register.filter +def readable_str(value): + replacements = { + "_": " ", + } + return reduce(lambda a, kv: a.replace(*kv), replacements.items(), value) + + +@register.filter +def all_fields_have_choices(form): + for field in form.fields: + if len(form.fields[field].choices) == 0: + return False + return True