Added mailto: links
authorThierry Florac <thierry.florac@onf.fr>
Mon, 11 Jul 2016 12:26:22 +0200
changeset 53 4acef7070de7
parent 52 d9400e3ca85d
child 54 e26ea933fb8e
Added mailto: links
src/pyams_content/component/links/__init__.py
src/pyams_content/component/links/interfaces/__init__.py
src/pyams_content/component/links/zmi/__init__.py
src/pyams_content/component/links/zmi/container.py
src/pyams_content/component/links/zmi/templates/widget-input.pt
--- a/src/pyams_content/component/links/__init__.py	Fri Jul 08 15:39:08 2016 +0200
+++ b/src/pyams_content/component/links/__init__.py	Mon Jul 11 12:26:22 2016 +0200
@@ -9,6 +9,8 @@
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
 # FOR A PARTICULAR PURPOSE.
 #
+from pyams_i18n.interfaces import II18n
+from pyams_utils.request import check_request
 
 __docformat__ = 'restructuredtext'
 
@@ -17,7 +19,7 @@
 
 # import interfaces
 from hypatia.interfaces import ICatalog
-from pyams_content.component.links.interfaces import IBaseLink, IInternalLink, IExternalLink
+from pyams_content.component.links.interfaces import IBaseLink, IInternalLink, IExternalLink, IMailtoLink
 from pyams_content.shared.common.interfaces import IWfSharedContent
 from pyams_form.interfaces.form import IFormContextPermissionChecker
 from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent, IObjectRemovedEvent
@@ -117,7 +119,7 @@
 
 @implementer(IExternalLink)
 class ExternalLink(BaseLink):
-    """external link persistent class"""
+    """External link persistent class"""
 
     url = FieldProperty(IExternalLink['url'])
     language = FieldProperty(IExternalLink['language'])
@@ -127,3 +129,20 @@
 
     def get_url(self, request, view_name=None):
         return self.url
+
+
+@implementer(IMailtoLink)
+class MailtoLink(BaseLink):
+    """Mailto link persistent class"""
+
+    address = FieldProperty(IMailtoLink['address'])
+
+    def get_editor_url(self):
+        request = check_request()
+        return 'mailto:{0} <{1}>'.format(II18n(self).query_attribute('title', request=request),
+                                         self.address)
+
+    def get_url(self, request, view_name=None):
+        request = check_request()
+        return 'mailto:{0} <{1}>'.format(II18n(self).query_attribute('title', request=request),
+                                         self.address)
--- a/src/pyams_content/component/links/interfaces/__init__.py	Fri Jul 08 15:39:08 2016 +0200
+++ b/src/pyams_content/component/links/interfaces/__init__.py	Mon Jul 11 12:26:22 2016 +0200
@@ -14,6 +14,7 @@
 
 
 # import standard library
+import re
 
 # import interfaces
 from zope.annotation.interfaces import IAttributeAnnotatable
@@ -24,7 +25,7 @@
 from pyams_sequence.schema import InternalReference
 from pyams_utils.schema import PersistentList
 from zope.container.constraints import containers, contains
-from zope.interface import Interface, Attribute
+from zope.interface import Interface
 from zope.schema import Choice, TextLine
 
 from pyams_content import _
@@ -80,6 +81,18 @@
                       required=False)
 
 
+EMAIL_REGEX = re.compile("[^@]+@[^@]+\.[^@]+")
+
+
+class IMailtoLink(IBaseLink):
+    """Mailto link interface"""
+
+    address = TextLine(title=_("Target address"),
+                       description=_("Target email address"),
+                       constraint=EMAIL_REGEX.match,
+                       required=True)
+
+
 class ILinkContainer(IContainer):
     """Links container"""
 
--- a/src/pyams_content/component/links/zmi/__init__.py	Fri Jul 08 15:39:08 2016 +0200
+++ b/src/pyams_content/component/links/zmi/__init__.py	Mon Jul 11 12:26:22 2016 +0200
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.links.interfaces import ILinkContainerTarget, IInternalLink, ILinkContainer, IBaseLink, \
-    IExternalLink
+    IExternalLink, IMailtoLink
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
 from pyams_i18n.interfaces import II18n
 from pyams_skin.interfaces.viewlet import IToolbarAddingMenu
@@ -25,7 +25,7 @@
 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
 
 # import packages
-from pyams_content.component.links import InternalLink, ExternalLink
+from pyams_content.component.links import InternalLink, ExternalLink, MailtoLink
 from pyams_content.component.links.zmi.container import LinkContainerView
 from pyams_form.form import AJAXAddForm, AJAXEditForm
 from pyams_form.security import ProtectedFormObjectMixin
@@ -248,3 +248,109 @@
                     'location': '#links.html'}
         else:
             return super(ExternalLinkPropertiesAJAXEditForm, self).get_ajax_output(changes)
+
+
+#
+# Mailto links views
+#
+
+
+@viewlet_config(name='add-mailto-link.menu', context=ILinkContainerTarget, view=LinkContainerView,
+                layer=IPyAMSLayer, manager=IToolbarAddingMenu, weight=52)
+class MailtoLinkAddMenu(ProtectedFormObjectMixin, ToolbarMenuItem):
+    """Mailto link add menu"""
+
+    label = _("Add mailto link")
+    label_css_class = 'fa fa-fw fa-envelope-o'
+
+    url = 'add-mailto-link.html'
+    modal_target = True
+
+
+@pagelet_config(name='add-mailto-link.html', context=ILinkContainerTarget, layer=IPyAMSLayer,
+                permission=MANAGE_CONTENT_PERMISSION)
+class MailtoLinkAddForm(AdminDialogAddForm):
+    """Mailto link add form"""
+
+    legend = _("Add new mailto link")
+    icon_css_class = 'fa fa-fw fa-envelope-o'
+
+    fields = field.Fields(IMailtoLink).omit('__parent__', '__name__')
+
+    @property
+    def ajax_handler(self):
+        origin = self.request.params.get('origin')
+        if origin == 'link':
+            return 'add-mailto-link-link.json'
+        else:
+            return 'add-mailto-link.json'
+
+    edit_permission = MANAGE_CONTENT_PERMISSION
+
+    def updateWidgets(self, prefix=None):
+        super(MailtoLinkAddForm, self).updateWidgets(prefix)
+        self.widgets['description'].label_css_class = 'textarea'
+
+    def create(self, data):
+        return MailtoLink()
+
+    def add(self, object):
+        ILinkContainer(self.context)['none'] = object
+
+
+@view_config(name='add-mailto-link.json', context=ILinkContainerTarget, request_type=IPyAMSLayer,
+             permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+class MailtoLinkAJAXAddForm(AJAXAddForm, MailtoLinkAddForm):
+    """Mailto link add form, JSON renderer"""
+
+    def get_ajax_output(self, changes):
+        return {'status': 'reload',
+                'location': '#links.html'}
+
+
+@view_config(name='add-mailto-link-link.json', context=ILinkContainerTarget, request_type=IPyAMSLayer,
+             permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+class MailtoLinkLinkAJAXAddForm(AJAXAddForm, MailtoLinkAddForm):
+    """Mailto link link add form, JSON renderer"""
+
+    def get_ajax_output(self, changes):
+        target = get_parent(self.context, ILinkContainerTarget)
+        container = ILinkContainer(target)
+        links = [{'id': link.__name__,
+                  'text': II18n(link).query_attribute('title', request=self.request)}
+                 for link in container.values()]
+        return {'status': 'callback',
+                'callback': 'PyAMS_content.links.refresh',
+                'options': {'links': links,
+                            'new_link': {'id': changes.__name__,
+                                         'text': II18n(changes).query_attribute('title', request=self.request)}}}
+
+
+@pagelet_config(name='properties.html', context=IMailtoLink, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+class MailtoLinkPropertiesEditForm(AdminDialogEditForm):
+    """Mailto link properties edit form"""
+
+    legend = _("Edit link properties")
+    icon_css_class = 'fa fa-fw fa-envelope-o'
+
+    fields = field.Fields(IMailtoLink).omit('__parent__', '__name__')
+    ajax_handler = 'properties.json'
+    edit_permission = MANAGE_CONTENT_PERMISSION
+
+    def updateWidgets(self, prefix=None):
+        super(MailtoLinkPropertiesEditForm, self).updateWidgets(prefix)
+        self.widgets['description'].label_css_class = 'textarea'
+
+
+@view_config(name='properties.json', context=IMailtoLink, request_type=IPyAMSLayer,
+             permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+class MailtoLinkPropertiesAJAXEditForm(AJAXEditForm, MailtoLinkPropertiesEditForm):
+    """Mailto link properties edit form, JSON renderer"""
+
+    def get_ajax_output(self, changes):
+        if ('title' in changes.get(IBaseLink, ())) or \
+           ('reference' in changes.get(IMailtoLink, ())):
+            return {'status': 'reload',
+                    'location': '#links.html'}
+        else:
+            return super(MailtoLinkPropertiesAJAXEditForm, self).get_ajax_output(changes)
--- a/src/pyams_content/component/links/zmi/container.py	Fri Jul 08 15:39:08 2016 +0200
+++ b/src/pyams_content/component/links/zmi/container.py	Mon Jul 11 12:26:22 2016 +0200
@@ -14,6 +14,7 @@
 
 
 # import standard library
+import html
 
 # import interfaces
 from pyams_content.component.extfile.interfaces import IExtFileContainer, IExtFileContainerTarget
@@ -162,7 +163,7 @@
             mapping = get_sequence_dict(obj.get_target())
             return mapping['text']
         else:
-            return obj.url
+            return html.escape(obj.get_url(self.request))
 
 
 @adapter_config(name='trash', context=(ILinkContainerTarget, IPyAMSLayer, LinkContainerTable), provides=IColumn)
--- a/src/pyams_content/component/links/zmi/templates/widget-input.pt	Fri Jul 08 15:39:08 2016 +0200
+++ b/src/pyams_content/component/links/zmi/templates/widget-input.pt	Mon Jul 11 12:26:22 2016 +0200
@@ -19,6 +19,13 @@
 					<span i18n:translate="">Add external link...</span>
 				</a>
 			</li>
+			<li class="small">
+				<a data-ams-url="add-mailto-link.html?origin=link"
+				   data-ams-stop-propagation="true" data-toggle="modal">
+					<i class="fa fa-fw fa-envelope-o"></i>
+					<span i18n:translate="">Add mailto link...</span>
+				</a>
+			</li>
 		</ul>
 	</div>
 	<div class="select2-parent">