diff --git a/froide/foirequest/models/attachment.py b/froide/foirequest/models/attachment.py index 4ea7dd7eb..417d7560b 100644 --- a/froide/foirequest/models/attachment.py +++ b/froide/foirequest/models/attachment.py @@ -388,12 +388,15 @@ def remove_file_and_delete(self): self.file.delete(save=False) self.delete() - def can_convert_to_pdf(self): + def is_filetype_convertable_to_pdf(self): from filingcabinet.pdf_utils import can_convert_to_pdf ft = self.filetype.lower() name = self.name.lower() - return self.converted_id is None and can_convert_to_pdf(ft, name=name) + return can_convert_to_pdf(ft, name=name) + + def can_convert_to_pdf(self): + return self.converted_id is None and self.is_filetype_convertable_to_pdf() def create_document(self, title=None): if self.document is not None: diff --git a/froide/foirequest/models/message.py b/froide/foirequest/models/message.py index 3925b1332..1bfd5d8e2 100644 --- a/froide/foirequest/models/message.py +++ b/froide/foirequest/models/message.py @@ -94,7 +94,12 @@ class MessageKind(models.TextChoices): MessageKind.IMPORT: "cloud-download", } -MANUAL_MESSAGE_KINDS = {MessageKind.POST, MessageKind.PHONE, MessageKind.VISIT} +MANUAL_MESSAGE_KINDS = { + MessageKind.POST, + MessageKind.PHONE, + MessageKind.VISIT, +} + MESSAGE_ID_PREFIX = "foimsg." @@ -643,7 +648,7 @@ def get_original_email_from_imap(self): return data def fails_authenticity(self): - if not self.is_response or not self.is_email: + if not self.is_response or not self.is_email or not self.email_headers: return checks = self.email_headers.get("authenticity") if not checks: diff --git a/froide/foirequest/serializers.py b/froide/foirequest/serializers.py index 3f33cd45c..9a237a6d1 100644 --- a/froide/foirequest/serializers.py +++ b/froide/foirequest/serializers.py @@ -274,6 +274,8 @@ class FoiMessageSerializer(serializers.HyperlinkedModelSerializer): read_only=True, ) status_name = serializers.CharField(source="get_status_display", read_only=True) + fails_authenticity = serializers.BooleanField(default=True, read_only=True) + is_escalation_message = serializers.BooleanField(default=False, read_only=True) class Meta: model = FoiMessage @@ -289,6 +291,7 @@ class Meta: "is_draft", "kind", "is_escalation", + "is_escalation_message", "content_hidden", "sender_public_body", "recipient_public_body", @@ -305,14 +308,17 @@ class Meta: "sender", "status_name", "last_modified_at", + "fails_authenticity", ] read_only_fields = [ "sent", "is_escalation", + "is_escalation_message", "content_hidden", "is_draft", "not_publishable", "last_modified_at", + "fails_authenticity", ] def _is_authenticated_read(self, obj): @@ -454,6 +460,9 @@ class FoiAttachmentSerializer(serializers.HyperlinkedModelSerializer): resource_uri = serializers.HyperlinkedIdentityField( view_name="api:attachment-detail", lookup_field="pk" ) + is_filetype_convertable_to_pdf = serializers.BooleanField( + default=False, read_only=True + ) converted = serializers.HyperlinkedRelatedField( view_name="api:attachment-detail", lookup_field="pk", @@ -485,6 +494,7 @@ class Meta: "file_url", "pending", "is_converted", + "is_filetype_convertable_to_pdf", "converted", "approved", "can_approve", diff --git a/froide/foirequest/signals.py b/froide/foirequest/signals.py index 324ff6095..f9c6bd402 100644 --- a/froide/foirequest/signals.py +++ b/froide/foirequest/signals.py @@ -137,7 +137,7 @@ def notify_user_message_received(sender, message=None, **kwargs): "user": sender.user, "publicbody": message.sender_public_body, "action_url": sender.user.get_autologin_url( - message.get_absolute_short_url() + short_request_url("foirequest-edit_message_flow_email", sender, message) ), }, priority=False, diff --git a/froide/foirequest/templates/foirequest/body/message/message.html b/froide/foirequest/templates/foirequest/body/message/message.html index c28c09850..2a2c51c53 100644 --- a/froide/foirequest/templates/foirequest/body/message/message.html +++ b/froide/foirequest/templates/foirequest/body/message/message.html @@ -207,14 +207,16 @@ {% endif %} {% endif %} + {# Redact button #} {% if object|can_write_foirequest:request or object|can_moderate_pii_foirequest:request %} {% render_message_redact_button message %} {% endif %} + {# Edit button #} {% if object|can_write_foirequest:request %} {% render_message_edit_button message %} {% endif %} {% endif %} - + {# Problem button #} {% render_problem_button message %} {% if object|can_moderate_foirequest:request and message.can_resend_bounce %} {% include "foirequest/body/message/toolbar/resend.html" %} diff --git a/froide/foirequest/templates/foirequest/edit_message_flow_email.html b/froide/foirequest/templates/foirequest/edit_message_flow_email.html new file mode 100644 index 000000000..204c6c55d --- /dev/null +++ b/froide/foirequest/templates/foirequest/edit_message_flow_email.html @@ -0,0 +1,66 @@ +{% extends "fullscreen_app.html" %} +{% load i18n %} +{% load static %} +{% load block_helper %} +{% load frontendbuild %} +{% load form_helper %} +{% load content_helper %} +{% load foirequest_tags %} +{% load problemreport_tags %} +{% block title %} + {% blocktrans with title=object.title %}Edit e-mail response for “{{ title }}”{% endblocktrans %} +{% endblock title %} +{% block navbar %} + {% include "header_reduced.html" %} +{% endblock navbar %} +{% block body %} +
+ {% translate "Edit e-mail response" as breadcrumb_label %} + {% include "foirequest/header/breadcrumb.html" with last_item=breadcrumb_label %} +
+ {# the form never submits, but is useful for checkValidity #} +
+ {% csrf_token %} + {# mw-100 crucial for pdf-redaction's dynamic maxWidth calculations #} + + + + + + + {# avoid whitespace, since this will be pre-wrap. spaceless didn't work... #} + + + + +
+ {% if object|can_write_foirequest:request or object|can_moderate_pii_foirequest:request %} + {% render_message_redact_button message is_edit_message_flow_email=True partial='modal' %} + {% endif %} + {% render_problem_button message is_edit_message_flow_email=True partial='modal' %} +{% endblock body %} +{% block scripts %} + {{ block.super }} + {% addfrontendbuild "request.js" %} + {% addfrontendbuild "publicbody.js" %} + {% addfrontendbuild "editmessageflow.js" %} + {% addfrontendbuild "messageredaction.js" %} + {% addfrontendbuild "fileuploader.js" %} +{% endblock scripts %} diff --git a/froide/foirequest/templates/foirequest/upload_postal_message_new.html b/froide/foirequest/templates/foirequest/edit_message_flow_postal.html similarity index 60% rename from froide/foirequest/templates/foirequest/upload_postal_message_new.html rename to froide/foirequest/templates/foirequest/edit_message_flow_postal.html index 2dfd5bd50..f839978bb 100644 --- a/froide/foirequest/templates/foirequest/upload_postal_message_new.html +++ b/froide/foirequest/templates/foirequest/edit_message_flow_postal.html @@ -4,6 +4,8 @@ {% load block_helper %} {% load frontendbuild %} {% load form_helper %} +{% load content_helper %} +{% load foirequest_tags %} {% block title %} {% blocktrans with title=object.title %}Upload postal mail for “{{ title }}”{% endblocktrans %} {% endblock title %} @@ -11,25 +13,25 @@ {% include "header_reduced.html" %} {% endblock navbar %} {% block body %} -
+
{% translate "Upload postal mail" as breadcrumb_label %} {% include "foirequest/header/breadcrumb.html" with last_item=breadcrumb_label %}
{# the form never submits, but is useful for checkValidity #} -
+ {% csrf_token %} {# mw-100 crucial for pdf-redaction's dynamic maxWidth calculations #} - + - +
{% endblock body %} {% block scripts %} {{ block.super }} {% addfrontendbuild "request.js" %} {% addfrontendbuild "publicbody.js" %} - {% addfrontendbuild "postupload.js" %} + {% addfrontendbuild "editmessageflow.js" %} {% addfrontendbuild "fileuploader.js" %} {% endblock scripts %} diff --git a/froide/foirequest/templates/foirequest/snippets/message_redact.html b/froide/foirequest/templates/foirequest/snippets/message_redact.html index 3789ac582..6c176d313 100644 --- a/froide/foirequest/templates/foirequest/snippets/message_redact.html +++ b/froide/foirequest/templates/foirequest/snippets/message_redact.html @@ -1,7 +1,7 @@ {% load i18n %} {% load markup %} {% load form_helper %} -{% if show_button %} +{% if is_redactable and render_button %}
+{% endif %} +{% if is_redactable and render_modal %} -
+{% endif %} diff --git a/froide/problem/templatetags/problemreport_tags.py b/froide/problem/templatetags/problemreport_tags.py index 38d7d511d..1d7c04ade 100644 --- a/froide/problem/templatetags/problemreport_tags.py +++ b/froide/problem/templatetags/problemreport_tags.py @@ -11,7 +11,9 @@ @register.inclusion_tag("problem/message_toolbar_item.html", takes_context=True) -def render_problem_button(context, message): +def render_problem_button( + context, message, is_edit_message_flow_email=False, partial=None +): request = context["request"] foirequest = message.request is_requester = ( @@ -39,10 +41,16 @@ def render_problem_button(context, message): # Assign message to problem to avoid query for problem in mes.problemreports: problem.message = mes + # overwrite to later return the message with .problemreports* + if mes == message: + message = mes return { "is_requester": is_requester, "request": request, "foirequest": foirequest, "message": message, + "is_edit_message_flow_email": is_edit_message_flow_email, + "render_button": partial is None or partial == "button", + "render_modal": partial is None or partial == "modal", } diff --git a/froide/problem/views.py b/froide/problem/views.py index 11af83a67..48952345c 100644 --- a/froide/problem/views.py +++ b/froide/problem/views.py @@ -34,7 +34,15 @@ def report_problem(request, message_pk): messages.add_message( request, messages.ERROR, _("Your report could not be created.") ) - return redirect(message) + redirect_to = ( + reverse( + "foirequest-edit_message_flow_email", + kwargs={"slug": message.request.slug, "message_id": message.id}, + ) + if request.POST.get("edit_message_flow_email") + else message + ) + return redirect(redirect_to) def get_moderation_data(request): diff --git a/froide/settings.py b/froide/settings.py index f175bcfd8..4965dbc30 100644 --- a/froide/settings.py +++ b/froide/settings.py @@ -576,7 +576,7 @@ def is_pkce_required(client_id): "help": "/help/", "throttled": "/help/", # TODO english? - "help_postupload_redaction": "/hilfe/plain/funktionen-der-plattform/schwaerzungen-durchfuehren/", + "help_editmessageflow_redaction": "/hilfe/plain/funktionen-der-plattform/schwaerzungen-durchfuehren/", "help_attachments_management": "/hilfe/plain/funktionen-der-plattform/anhange-verwalten/", }, "mobile_app_install_url": None, # TODO diff --git a/frontend/javascript/components/docupload/attachment-icon-preview.vue b/frontend/javascript/components/docupload/attachment-icon-preview.vue index f723732bf..7d00580c9 100644 --- a/frontend/javascript/components/docupload/attachment-icon-preview.vue +++ b/frontend/javascript/components/docupload/attachment-icon-preview.vue @@ -23,7 +23,8 @@ const { attachment, actions, nudgeRedaction, big } = defineProps({ }, actions: Boolean, nudgeRedaction: Boolean, - big: Boolean + big: Boolean, + previewHideInfoSidebar: Boolean, }) const pdfRedactionAtt = ref(null) @@ -131,7 +132,7 @@ const iconTooltipTexts = computed(() => (needsRedaction.value && nudgeRedaction)