From 172e60df04f8fefa0deac49deb046b38acfe6ba8 Mon Sep 17 00:00:00 2001
From: Rafael Monnerat <rafael@nexedi.com>
Date: Wed, 22 Jan 2025 14:37:52 +0000
Subject: [PATCH] erp5_administration: Implement RSS notification for Activity
 Failures

   This aims to allow the admin know if there is or not an activity failure on ERP5.

   It outputs at most one entry if there is at least one activity failure, based on the standard sort, (which consider priority and date) and using uid as guid, if provides a stable output even if other activities fail later on (so we dont have a flickeing output).

   DateTime.earliestTime is used to refresh dates daily (leading to new entry on most of rss readers) and to not expose when the activity was created,

   This requires no authentication.
---
 .../ERP5Site_getPendingErrorList.py           |  29 +++
 .../ERP5Site_getPendingErrorList.xml          |  70 ++++++
 .../ERP5Site_viewPendingErrorListAsRSS.xml    | 139 ++++++++++++
 .../listbox.xml                               | 202 ++++++++++++++++++
 4 files changed, 440 insertions(+)
 create mode 100644 bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.py
 create mode 100644 bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.xml
 create mode 100644 bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS.xml
 create mode 100644 bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS/listbox.xml

diff --git a/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.py b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.py
new file mode 100644
index 0000000000..58a0db49d8
--- /dev/null
+++ b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.py
@@ -0,0 +1,29 @@
+from Products.ERP5Type.Document import newTempBase
+from DateTime import DateTime
+from zExceptions import Unauthorized
+if REQUEST is not None:
+  raise Unauthorized
+
+portal = context.getPortalObject()
+
+# Use only the first entry. This prevents change the rss content
+# too often whenever multiple activities are failing over time.
+message_list = portal.portal_activities.getMessageTempObjectList(processing_node=-2,
+                                                                 count=1)
+if not len(message_list):
+  return []
+
+message = portal.Base_translateString('You have one or more activity failures.')
+
+# Make compatible with renderjs_runner
+web_site = context.getWebSiteValue()
+if web_site is None:
+  web_site_url = portal.absolute_url()
+else:
+  web_site_url = web_site.absolute_url() + "/#"
+return [
+  newTempBase(portal, "rss_entry",
+    uid=message_list[0].uid,
+    date=DateTime().earliestTime(),
+    link="%s/portal_activities" % web_site_url,
+    title=message)]
diff --git a/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.xml b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.xml
new file mode 100644
index 0000000000..f46edc1735
--- /dev/null
+++ b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_getPendingErrorList.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="_reconstructor" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                  <global name="object" module="__builtin__"/>
+                  <none/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>REQUEST=None, **kw</string> </value>
+        </item>
+        <item>
+            <key> <string>_proxy_roles</string> </key>
+            <value>
+              <tuple>
+                <string>Manager</string>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ERP5Site_getPendingErrorList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS.xml b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS.xml
new file mode 100644
index 0000000000..3dfd89b54f
--- /dev/null
+++ b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ERP5 Form" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="_reconstructor" module="copy_reg"/>
+                </klass>
+                <tuple>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                  <global name="object" module="__builtin__"/>
+                  <none/>
+                </tuple>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>action_title</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string>application/x-www-form-urlencoded</string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>bottom</string>
+                <string>hidden</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>rss_view</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Pending Errors</string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>update_action_title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS/listbox.xml b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS/listbox.xml
new file mode 100644
index 0000000000..61b8670f71
--- /dev/null
+++ b/bt5/erp5_administration/SkinTemplateItem/portal_skins/erp5_administration/ERP5Site_viewPendingErrorListAsRSS/listbox.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>all_columns</string>
+                <string>columns</string>
+                <string>count_method</string>
+                <string>editable_columns</string>
+                <string>hide_rows_on_no_search_criterion</string>
+                <string>lines</string>
+                <string>list_method</string>
+                <string>portal_types</string>
+                <string>search_columns</string>
+                <string>selection_name</string>
+                <string>sort</string>
+                <string>sort_columns</string>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>all_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>title</string>
+                          <string>title</string>
+                        </tuple>
+                        <tuple>
+                          <string>link</string>
+                          <string>link</string>
+                        </tuple>
+                        <tuple>
+                          <string>uid</string>
+                          <string>guid</string>
+                        </tuple>
+                        <tuple>
+                          <string>date</string>
+                          <string>pubDate</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>count_method</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_list_mode_listbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>hide_rows_on_no_search_criterion</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>lines</string> </key>
+                    <value> <int>30</int> </value>
+                </item>
+                <item>
+                    <key> <string>list_method</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>portal_types</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>search_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>selection_name</string> </key>
+                    <value> <string>pending_failure_selection</string> </value>
+                </item>
+                <item>
+                    <key> <string>sort</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>sort_columns</string> </key>
+                    <value>
+                      <list/>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Pending Errors</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Method" module="Products.Formulator.MethodField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>method_name</string> </key>
+            <value> <string>ERP5Site_getPendingErrorList</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
-- 
2.30.9