src/pyams_zmi/control_panel.py
changeset 3 b284b151f292
parent 0 9131229e2982
child 4 0ff044965637
--- a/src/pyams_zmi/control_panel.py	Sat Feb 28 16:20:01 2015 +0100
+++ b/src/pyams_zmi/control_panel.py	Tue Mar 03 16:53:26 2015 +0100
@@ -14,10 +14,12 @@
 
 
 # import standard library
+from html import escape
 
 # import interfaces
 from pyams_skin.interfaces import IInnerPage, IPageHeader, IContentHelp
 from pyams_skin.layer import IPyAMSLayer
+from pyams_utils.interfaces.site import IOptionalUtility
 from pyams_zmi.interfaces.menu import IControlPanelMenu, IUtilitiesMenu
 from pyams_zmi.layer import IAdminLayer
 from z3c.table.interfaces import IValues, IColumn
@@ -27,15 +29,18 @@
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_skin.container import ContainerView
 from pyams_skin.help import ContentHelp
-from pyams_skin.table import BaseTable
+from pyams_skin.table import BaseTable, TrashColumn
 from pyams_skin.viewlet.menu import MenuItem
 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
+from pyams_utils.registry import registered_utilities
 from pyams_utils.text import text_to_html
+from pyams_utils.url import absolute_url
 from pyams_viewlet.manager import viewletmanager_config
 from pyams_viewlet.viewlet import viewlet_config
 from pyams_zmi.view import AdminView
+from pyramid.view import view_config
 from z3c.table.column import GetAttrColumn
-from zope.interface import implementer
+from zope.interface import implementer, Interface
 
 from pyams_zmi import _
 
@@ -63,6 +68,23 @@
     title = _("Site utilities")
     cssClasses = {'table': 'table table-bordered table-striped table-hover table-tight datatable'}
 
+    @property
+    def data_attributes(self):
+        attrs = super(UtilitiesTable, self).data_attributes
+        attrs['table'] = {'data-ams-location': absolute_url(self.context, self.request),
+                          'data-ams-delete-target': 'delete-utility.json'}
+        return attrs
+
+
+@adapter_config(name='trash', context=(Interface, IAdminLayer, UtilitiesTable), provides=IColumn)
+class UtilitiesTrashColumn(TrashColumn):
+    """Utilities trash column"""
+
+    icon_hint = _("Delete utility")
+    permission = 'system.manage'
+
+    checker = lambda col, x: IOptionalUtility.providedBy(x)
+
 
 @adapter_config(context=(ISite, IAdminLayer, UtilitiesTable), provides=IValues)
 class UtilitiesValuesAdapter(ContextRequestViewAdapter):
@@ -93,38 +115,34 @@
     subtitle = _("Utilities")
 
 
-#
-# Registrations views and adapters
-#
-
-@viewlet_config(name='registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu,
-                permission='system.view', weight=1)
-class RegistrationsMenuItem(MenuItem):
-    """Registrations menu"""
-
-    label = _("Registrations")
-    url = '#registrations.html'
+@view_config(name='delete-utility.json', context=ISite, request_type=IPyAMSLayer,
+             permission='system.manage', renderer='json', xhr=True)
+def delete_utility(request):
+    """Delete utility from site manager"""
+    translate = request.localizer.translate
+    name = request.params.get('object_name')
+    if not name:
+        return {'status': 'message',
+                'messagebox': {'status': 'error',
+                               'content': translate(_("No provided object_name argument!"))}}
+    manager = request.context.getSiteManager()
+    if name not in manager:
+        return {'status': 'message',
+                'messagebox': {'status': 'error',
+                               'content': translate(_("Given utility name doesn't exist!"))}}
+    del manager[name]
+    return {'status': 'success'}
 
 
-class RegistrationsTable(BaseTable):
-    """Utilities registrations table"""
+#
+# Common registrations views and adapters
+#
 
-    id = 'registrations_table'
-    title = _("Utilities registrations")
-
-    data_attributes = {}
+class IRegistrationsTable(Interface):
+    """Registrations view marker interface"""
 
 
-@adapter_config(context=(ISite, IAdminLayer, RegistrationsTable), provides=IValues)
-class RegistrationsValuesAdapter(ContextRequestViewAdapter):
-    """Utilities values adapter"""
-
-    @property
-    def values(self):
-        return list(self.context.getSiteManager().registeredUtilities())
-
-
-@adapter_config(name='component', context=(ISite, IAdminLayer, RegistrationsTable), provides=IColumn)
+@adapter_config(name='component', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn)
 class RegistrationsComponentColumn(GetAttrColumn):
     """Registrations component column"""
 
@@ -136,10 +154,17 @@
         return self.request.localizer.translate(self._header)
 
     def getValue(self, obj):
-        return obj.component.__name__
+        component = obj.component
+        if component is not None:
+            name = getattr(component, '__name__', None)
+            if not name:
+                name = str(component.__class__)
+        else:
+            name = str(obj.factory)
+        return escape(name)
 
 
-@adapter_config(name='interface', context=(ISite, IAdminLayer, RegistrationsTable), provides=IColumn)
+@adapter_config(name='interface', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn)
 class RegistrationsInterfaceColumn(GetAttrColumn):
     """Registrations interface column"""
 
@@ -154,7 +179,7 @@
         return text_to_html(str(obj.provided))
 
 
-@adapter_config(name='name', context=(ISite, IAdminLayer, RegistrationsTable), provides=IColumn)
+@adapter_config(name='name', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn)
 class RegistrationsNameColumn(GetAttrColumn):
     """Registrations name column"""
 
@@ -169,29 +194,61 @@
         return obj.name or _('< no name >')
 
 
-@pagelet_config(name='registrations.html', context=ISite, layer=IPyAMSLayer, permission='system.view')
+#
+# Local registrations views
+#
+
+@viewlet_config(name='local-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu,
+                permission='system.view', weight=1)
+class LocalRegistrationsMenuItem(MenuItem):
+    """Local registrations menu"""
+
+    label = _("Local registrations")
+    url = '#local-registrations.html'
+
+
+@implementer(IRegistrationsTable)
+class LocalRegistrationsTable(BaseTable):
+    """Local utilities registrations table"""
+
+    id = 'local_registrations_table'
+    title = _("Local utilities registrations")
+
+    data_attributes = {}
+
+
+@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsTable), provides=IValues)
+class LocalRegistrationsValuesAdapter(ContextRequestViewAdapter):
+    """Local utilities values adapter"""
+
+    @property
+    def values(self):
+        return list(self.context.getSiteManager().registeredUtilities())
+
+
+@pagelet_config(name='local-registrations.html', context=ISite, layer=IPyAMSLayer, permission='system.view')
 @implementer(IInnerPage)
-class RegistrationsView(AdminView, ContainerView):
+class LocalRegistrationsView(AdminView, ContainerView):
     """Registrations view"""
 
-    table_class = RegistrationsTable
+    table_class = LocalRegistrationsTable
 
     def __init__(self, context, request):
-        super(RegistrationsView, self).__init__(context, request)
+        super(LocalRegistrationsView, self).__init__(context, request)
 
 
-@adapter_config(context=(ISite, IAdminLayer, RegistrationsView), provides=IPageHeader)
-class RegistrationsHeaderAdapter(ContextRequestViewAdapter):
-    """Registrations header adapter"""
+@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IPageHeader)
+class LocalRegistrationsHeaderAdapter(ContextRequestViewAdapter):
+    """Local registrations header adapter"""
 
     icon_class = 'fa fa-fw fa-codepen'
     title = _("Control panel")
     subtitle = _("Local utilities registry")
 
 
-@adapter_config(context=(ISite, IAdminLayer, RegistrationsView), provides=IContentHelp)
-class RegistrationsHelpAdapter(ContentHelp):
-    """Registrations help adapter"""
+@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IContentHelp)
+class LocalRegistrationsHelpAdapter(ContentHelp):
+    """Local registrations help adapter"""
 
     header = _("Local registry utilities")
     message = _("""A local registry is a registry defining utilities stored into
@@ -200,3 +257,68 @@
 You can manage these utilities and modify their properties and site's behaviour without
 modifying the application.""")
     message_format = 'rest'
+
+
+#
+# Global registrations views
+#
+
+@viewlet_config(name='global-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu,
+                permission='system.view', weight=2)
+class GlobalRegistrationsMenuItem(MenuItem):
+    """Global registrations menu"""
+
+    label = _("Global registrations")
+    url = '#global-registrations.html'
+
+
+@implementer(IRegistrationsTable)
+class GlobalRegistrationsTable(BaseTable):
+    """Utilities global registrations table"""
+
+    id = 'global_registrations_table'
+    title = _("Global utilities registrations")
+
+    data_attributes = {}
+
+
+@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsTable), provides=IValues)
+class GlobalRegistrationsValuesAdapter(ContextRequestViewAdapter):
+    """Global utilities values adapter"""
+
+    @property
+    def values(self):
+        return list(registered_utilities())
+
+
+@pagelet_config(name='global-registrations.html', context=ISite, layer=IPyAMSLayer, permission='system.view')
+@implementer(IInnerPage)
+class GlobalRegistrationsView(AdminView, ContainerView):
+    """Global registrations view"""
+
+    table_class = GlobalRegistrationsTable
+
+    def __init__(self, context, request):
+        super(GlobalRegistrationsView, self).__init__(context, request)
+
+
+@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IPageHeader)
+class GlobalRegistrationsHeaderAdapter(ContextRequestViewAdapter):
+    """Global registrations header adapter"""
+
+    icon_class = 'fa fa-fw fa-codepen'
+    title = _("Control panel")
+    subtitle = _("Global utilities registry")
+
+
+@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IContentHelp)
+class GlobalRegistrationsHelpAdapter(ContentHelp):
+    """Global registrations help adapter"""
+
+    header = _("Global registry utilities")
+    message = _("""The global registry groups local utilities as well as utilities registered outside
+site's Object Database (ZODB).
+
+These utilities are declared statically (generally using include or ZCML directives) and can't be setup
+without modifying site configuration.""")
+    message_format = 'rest'