From 614eb568d5d997243695645414cc4df1a1f7b09f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sun, 13 Feb 2022 17:32:46 +0100
Subject: [PATCH] backoffice: include action details in tracing inspect section
 (#60689)

---
 tests/backoffice_pages/test_form_inspect.py | 15 ++++++++++++
 wcs/backoffice/management.py                | 10 +++++++-
 wcs/workflows.py                            | 27 +++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/tests/backoffice_pages/test_form_inspect.py b/tests/backoffice_pages/test_form_inspect.py
index d029ff4df..248942c70 100644
--- a/tests/backoffice_pages/test_form_inspect.py
+++ b/tests/backoffice_pages/test_form_inspect.py
@@ -623,6 +623,21 @@ def test_inspect_page_actions_traces(pub):
     )
     assert action_links[-1] == 'http://example.net/backoffice/workflows/2/global-actions/1/items/1/'
 
+    # check details are available
+    assert 'Email (to Recipient)' in [
+        x.text_content().split(' ', 2)[-1] for x in resp.pyquery('#inspect-timeline li')
+    ]
+    # and there's no crash when part of the workflow changes
+    workflow.global_actions = []
+    workflow.store()
+    get_app(pub).get(formdata.get_url(backoffice=True) + 'inspect')
+    workflow.possible_status[0].items = []
+    workflow.store()
+    get_app(pub).get(formdata.get_url(backoffice=True) + 'inspect')
+    workflow.possible_status = []
+    workflow.store()
+    get_app(pub).get(formdata.get_url(backoffice=True) + 'inspect')
+
 
 def test_inspect_page_missing_carddef_error(pub):
     create_user(pub, is_admin=True)
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index e13375982..90e1d5e1b 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -3387,12 +3387,20 @@ class FormBackOfficeStatusPage(FormStatusPage):
                                 url = '#missing-%s' % action_id
                             r += htmltext(
                                 '<li><span class="datetime">%s</span> '
-                                '<a class="tracing-link" href="%s">%s</a></li>'
+                                '<a class="tracing-link" href="%s">%s</a>'
                             ) % (
                                 action_ts.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3],
                                 url,
                                 action_label,
                             )
+                            real_action = part.get_real_action(
+                                self.filled.formdef.workflow, wf_status, action_id
+                            )
+                            if real_action:
+                                details = real_action.get_inspect_details()
+                                if details:
+                                    r += htmltext(' <span>(%s)</span>') % details
+                            r += htmltext('</li>')
 
             r += htmltext('</ul>')
             r += htmltext('</div>')
diff --git a/wcs/workflows.py b/wcs/workflows.py
index 7a7bac4e1..e2b10eb6c 100644
--- a/wcs/workflows.py
+++ b/wcs/workflows.py
@@ -414,6 +414,26 @@ class ActionsTracingEvolutionPart(EvolutionPart):
         status = workflow.get_status(status_id)
         return status.get_admin_url()
 
+    def get_real_action(self, workflow, status_id, action_id):
+        if self.is_global_event():
+            global_action_id = self.event_args[0]
+            try:
+                global_action = [x for x in workflow.global_actions if x.id == global_action_id][0]
+            except IndexError:
+                return None
+            items = global_action.items
+        else:
+            try:
+                status = workflow.get_status(status_id)
+            except KeyError:
+                return None
+            items = status.items
+        try:
+            real_action = [x for x in items if x.id == action_id][0]
+        except IndexError:
+            real_action = None
+        return real_action
+
 
 class DuplicateGlobalActionNameError(Exception):
     pass
@@ -2176,6 +2196,9 @@ class WorkflowStatusItem(XmlSerialisable):
     def get_line_details(self):
         return ''
 
+    def get_inspect_details(self):
+        return getattr(self, 'label', '')
+
     def render_list_of_roles(self, roles):
         return self.parent.parent.render_list_of_roles(roles)
 
@@ -3136,6 +3159,10 @@ class SendmailWorkflowStatusItem(WorkflowStatusItem):
         else:
             return _('not completed')
 
+    def get_inspect_details(self):
+        if self.to:
+            return _('to %s') % self.render_list_of_roles_or_emails(self.to)
+
     def get_parameters(self):
         parameters = ('to', 'mail_template', 'subject', 'body', 'attachments', 'custom_from', 'condition')
         if (
-- 
2.34.1

