Skip to content

Commit a5c9ed2

Browse files
committed
Added esign annotation admin view
1 parent 8fc8f77 commit a5c9ed2

File tree

5 files changed

+128
-0
lines changed

5 files changed

+128
-0
lines changed

imio/dms/mail/browser/actionspanel.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from imio.actionspanel.browser.views import ActionsPanelView
44
from imio.dms.mail.dmsmail import filter_dmsincomingmail_assigned_users
55
from imio.helpers.cache import get_plone_groups_for_user
6+
from imio.helpers.security import check_zope_admin
67
from plone import api
78
from plone.memoize import ram
89
from Products.CMFPlone.interfaces import IHideFromBreadcrumbs
@@ -159,12 +160,14 @@ class DmsActionsPanelViewlet(ActionsPanelViewlet):
159160

160161

161162
class SigningFieldsetActionsPanelView(ActionsPanelView):
163+
"""Actions panel for signing actions located in outgoing mail signing fieldset"""
162164

163165
_fieldset = "signing"
164166

165167
def __init__(self, context, request):
166168
super(SigningFieldsetActionsPanelView, self).__init__(context, request)
167169
self.ACCEPTABLE_ACTIONS = ["edit", "approvals"]
170+
self.SECTIONS_TO_RENDER += ("renderSigningAnnotationInfo",)
168171

169172
@property
170173
def fieldset(self):
@@ -175,6 +178,11 @@ def renderEdit(self):
175178
return ViewPageTemplateFile("templates/fieldset_actions_panel_edit.pt")(self)
176179
return ""
177180

181+
def renderSigningAnnotationInfo(self):
182+
if check_zope_admin():
183+
return ViewPageTemplateFile("templates/fieldset_actions_panel_signing_annotation_info.pt")(self)
184+
return ""
185+
178186
@ram.cache(actionspanelview_cachekey)
179187
def SigningFieldsetActionsPanelView__call__(
180188
self,

imio/dms/mail/browser/configure.zcml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@
5555
permission="cmf.ModifyPortalContent"
5656
/>
5757

58+
<browser:page
59+
for="imio.dms.mail.dmsmail.IImioDmsOutgoingMail"
60+
name="signing-annotation-info"
61+
class=".views.SigningAnnotationInfoView"
62+
permission="cmf.ManagePortal"
63+
/>
64+
5865
<browser:page
5966
for="imio.dms.mail.dmsmail.IImioDmsOutgoingMail"
6067
name="render_email_signature"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<td class="noPadding" tal:define="dummy view/saveHasActions;
2+
useIcons view/useIcons;">
3+
<tal:comment replace="nothing">Icon</tal:comment>
4+
<a tal:condition="useIcons"
5+
tal:attributes="href string:${context/absolute_url}/@@signing-annotation-info;
6+
target python: view.kwargs.get('edit_action_target', '_blank');"
7+
title="Annotation info (Zope admin only)">
8+
<img tal:attributes="src string:${view/portal_url}/search_icon.png" title="Annotation info" />
9+
</a>
10+
<tal:comment replace="nothing">Button</tal:comment>
11+
<form tal:condition="not: useIcons"
12+
tal:attributes="action string:${context/absolute_url}/@@signing-annotation-info;">
13+
<input type="submit" value="Annotation info"
14+
class="apButton apButtonAction"/>
15+
</form>
16+
</td>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
2+
xmlns:tal="http://xml.zope.org/namespaces/tal"
3+
xmlns:metal="http://xml.zope.org/namespaces/metal"
4+
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
5+
metal:use-macro="context/main_template/macros/master"
6+
i18n:domain="imio.dms.mail">
7+
<body>
8+
<metal:bodytext fill-slot="content-core">
9+
<h2>idm.approval annotation</h2>
10+
<pre style="background: #f5f5f5; color: #333; padding: 1em; overflow: auto;"
11+
tal:content="structure view/approval_annot_html" />
12+
13+
<tal:esign tal:repeat="session view/esign_sessions">
14+
<h2 tal:content="python:'imio.esign session (id: {})'.format(session[0])"></h2>
15+
<pre style="background: #f5f5f5; color: #333; padding: 1em; overflow: auto;"
16+
tal:content="structure python:view.esign_session_html(session[1])" />
17+
</tal:esign>
18+
</metal:bodytext>
19+
</body>
20+
</html>

imio/dms/mail/browser/views.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- coding: utf-8 -*-
22
from AccessControl import getSecurityManager
3+
from AccessControl import Unauthorized
34
from Acquisition import aq_inner
45
from collective.ckeditortemplates.cktemplate import ICKTemplate
56
from datetime import datetime
67
from eea.faceted.vocabularies.autocomplete import IAutocompleteSuggest
8+
from html import escape
79
from imio.dms.mail import _
810
from imio.dms.mail import _tr
911
from imio.dms.mail import PMH_ENABLED
@@ -15,11 +17,13 @@
1517
from imio.dms.mail.interfaces import IPersonnelContact
1618
from imio.dms.mail.utils import current_user_groups_ids
1719
from imio.dms.mail.utils import get_dms_config
20+
from imio.dms.mail.utils import persistent_to_native
1821
from imio.esign import manage_session_perm
1922
from imio.esign.browser.actions import RemoveItemFromSessionView
2023
from imio.esign.browser.views import ExternalSessionCreateView
2124
from imio.esign.browser.views import SessionsListingView
2225
from imio.esign.config import get_registry_enabled
26+
from imio.esign.utils import get_session_annotation
2327
from imio.esign.utils import remove_files_from_session
2428
from imio.helpers.content import richtextval
2529
from imio.helpers.content import uuidToObject
@@ -28,6 +32,7 @@
2832
from imio.helpers.emailer import get_mail_host
2933
from imio.helpers.emailer import send_email
3034
from imio.helpers.fancytree.views import BaseRenderFancyTree
35+
from imio.helpers.security import check_zope_admin
3136
from imio.helpers.workflow import do_transitions
3237
from imio.helpers.xhtml import object_link
3338
from plone import api
@@ -50,6 +55,8 @@
5055
from zope.pagetemplate.pagetemplate import PageTemplate
5156

5257
import json
58+
import pprint
59+
import re
5360

5461

5562
class CreateFromTemplateForm(BaseRenderFancyTree):
@@ -668,3 +675,73 @@ def get_link_url(item):
668675
result = sorted(result, key=lambda x: x['id'] == "plus")
669676

670677
return result
678+
679+
680+
class SigningAnnotationInfoView(BrowserView):
681+
"""Admin-only view displaying idm.approval and imio.esign session annotations for an outgoing mail."""
682+
683+
index = ViewPageTemplateFile("templates/signing_annotation_info.pt")
684+
685+
def __call__(self):
686+
if not check_zope_admin():
687+
raise Unauthorized
688+
return self.index()
689+
690+
def _uid_to_link(self, uid):
691+
"""Return an HTML link for an object UID, or the UID if not found."""
692+
obj = uuidToObject(uid, unrestricted=True)
693+
if obj is None:
694+
return u"<span title='not found'>{}</span>".format(safe_unicode(uid))
695+
url = obj.absolute_url()
696+
title = escape(safe_unicode(getattr(obj, 'title', '') or uid))
697+
path = escape(u"/".join(obj.getPhysicalPath()))
698+
return u"<a href='{}' title='{}'>{}</a>".format(url, path, title)
699+
700+
def _render_value(self, value, indent=u""):
701+
"""Render a value, replacing UIDs with links where possible."""
702+
inner = indent + u" "
703+
if isinstance(value, dict):
704+
if not value:
705+
return u"{}"
706+
lines = [u"{"]
707+
for k, v in sorted(value.items()):
708+
lines.append(u"{}{!r}: {},".format(inner, k, self._render_value(v, inner)))
709+
lines.append(u"{}}}".format(indent))
710+
return u"\n".join(lines)
711+
elif isinstance(value, (list, tuple)):
712+
if not value:
713+
return u"[]"
714+
lines = [u"["]
715+
for item in value:
716+
lines.append(u"{}{},".format(inner, self._render_value(item, inner)))
717+
lines.append(u"{}]".format(indent))
718+
return u"\n".join(lines)
719+
elif isinstance(value, basestring) and re.match(r'^[0-9a-f]{32}$', value):
720+
# Looks like a UUID
721+
return self._uid_to_link(value)
722+
else:
723+
return safe_unicode(pprint.pformat(value))
724+
725+
@property
726+
def approval_annot_html(self):
727+
approval = IOMApproval(self.context)
728+
native = persistent_to_native(approval.annot)
729+
return self._render_value(native)
730+
731+
@property
732+
def esign_sessions(self):
733+
"""Return list of (session_id, session_data) for all sessions."""
734+
approval = IOMApproval(self.context)
735+
session_ids = approval.annot.get("session_ids", [])
736+
if not session_ids:
737+
return []
738+
annot = get_session_annotation()
739+
result = []
740+
for session_id in session_ids:
741+
session = annot["sessions"].get(session_id)
742+
if session is not None:
743+
result.append((session_id, persistent_to_native(session)))
744+
return sorted(result)
745+
746+
def esign_session_html(self, session_data):
747+
return self._render_value(session_data)

0 commit comments

Comments
 (0)