Added back-office configuration interface and classes
authorThierry Florac <thierry.florac@onf.fr>
Wed, 07 Oct 2015 17:53:40 +0200
changeset 85 0dd5876f9d70
parent 84 25cf058f7e1d
child 86 0b28fe5fd535
Added back-office configuration interface and classes
src/pyams_skin/configuration.py
src/pyams_skin/interfaces/configuration.py
--- a/src/pyams_skin/configuration.py	Wed Oct 07 17:52:40 2015 +0200
+++ b/src/pyams_skin/configuration.py	Wed Oct 07 17:53:40 2015 +0200
@@ -18,8 +18,9 @@
 
 # import interfaces
 from pyams_skin.interfaces.configuration import IStaticConfiguration, IConfiguration, \
-    SKIN_CONFIGURATION_KEY
-from pyams_utils.interfaces.site import IStaticConfigurationManager, IConfigurationManager, IConfigurationFactory
+    SKIN_CONFIGURATION_KEY, IBackOfficeConfiguration, SKIN_BACK_CONFIGURATION_KEY
+from pyams_utils.interfaces.site import IStaticConfigurationManager, IConfigurationManager, IConfigurationFactory, \
+    IBackOfficeConfigurationFactory
 from pyams_utils.interfaces.tales import ITALESExtension
 from zope.annotation.interfaces import IAnnotations
 from zope.traversing.interfaces import ITraversable
@@ -41,6 +42,10 @@
 from pyams_skin import _
 
 
+#
+# Static configuration
+#
+
 @adapter_config(context=(IStaticConfigurationManager, Interface, Interface), provides=IStaticConfiguration)
 class StaticConfiguration(object):
     """Default static configuration"""
@@ -89,6 +94,11 @@
         return registry.queryMultiAdapter((target, self.request, self.view), IStaticConfiguration)
 
 
+#
+# Dynamic front-office configuration
+# May be overriden by custom applications
+#
+
 @implementer(IConfiguration)
 class Configuration(Persistent, Contained):
     """Manageable configuration"""
@@ -107,10 +117,9 @@
     configuration = annotations.get(SKIN_CONFIGURATION_KEY)
     if configuration is None:
         registry = check_request().registry
-        factory = registry.queryAdapter(context, IConfigurationFactory)
-        if factory is not None:
-            configuration = annotations[SKIN_CONFIGURATION_KEY] = factory()
-            locate(configuration, context, '++configuration++')
+        factory = registry.queryAdapter(context, IConfigurationFactory, default=Configuration)
+        configuration = annotations[SKIN_CONFIGURATION_KEY] = factory()
+        locate(configuration, context, '++configuration++')
     return configuration
 
 
@@ -142,3 +151,63 @@
         request.context = configuration.icon
         return MediaFileView(request)
     return HTTPNotFound()
+
+
+#
+# Dynamic back-office configuration
+# May be overriden by custom applications
+#
+
+@implementer(IBackOfficeConfiguration)
+class BackOfficeConfiguration(Persistent, Contained):
+    """Back-office manageable configuration"""
+
+    title = FieldProperty(IBackOfficeConfiguration['title'])
+    login_header = FieldProperty(IBackOfficeConfiguration['login_header'])
+    login_footer = FieldProperty(IBackOfficeConfiguration['login_footer'])
+    icon = FileProperty(IBackOfficeConfiguration['icon'])
+    logo = FileProperty(IBackOfficeConfiguration['logo'])
+    display_content_icon = FieldProperty(IBackOfficeConfiguration['display_content_icon'])
+
+
+@adapter_config(context=IConfigurationManager, provides=IBackOfficeConfiguration)
+def BackOfficeConfigurationFactory(context):
+    """Back-office configuration factory"""
+    annotations = IAnnotations(context)
+    configuration = annotations.get(SKIN_BACK_CONFIGURATION_KEY)
+    if configuration is None:
+        registry = check_request().registry
+        factory = registry.queryAdapter(context, IBackOfficeConfigurationFactory, default=BackOfficeConfiguration)
+        configuration = annotations[SKIN_BACK_CONFIGURATION_KEY] = factory()
+        locate(configuration, context, '++back-configuration++')
+    return configuration
+
+
+@adapter_config(name='back_configuration', context=(Interface, Interface, Interface), provides=ITALESExtension)
+class BackOfficeConfigurationTalesExtension(ContextRequestViewAdapter):
+    """extension:back_configuration TALES expression"""
+
+    def render(self, context=None):
+        if context is None:
+            context = self.context
+        manager = get_parent(context, IConfigurationManager)
+        if manager is not None:
+            return IBackOfficeConfiguration(manager)
+
+
+@adapter_config(name='back-configuration', context=IConfigurationManager, provides=ITraversable)
+class BackOfficeConfigurationTraverser(ContextAdapter):
+    """++back-configuration++ namespace traverser"""
+
+    def traverse(self, name, furtherpath=None):
+        return IBackOfficeConfiguration(self.context)
+
+
+@view_config(name='back-favicon.ico', context=IConfigurationManager)
+def back_office_site_icon(request):
+    configuration = IBackOfficeConfiguration(request.context)
+    if configuration.icon is not None:
+        request = request.copy()
+        request.context = configuration.icon
+        return MediaFileView(request)
+    return HTTPNotFound()
--- a/src/pyams_skin/interfaces/configuration.py	Wed Oct 07 17:52:40 2015 +0200
+++ b/src/pyams_skin/interfaces/configuration.py	Wed Oct 07 17:53:40 2015 +0200
@@ -21,7 +21,7 @@
 # import packages
 from pyams_file.schema import ImageField
 from zope.interface import Interface, Attribute
-from zope.schema import TextLine, Choice, Bool
+from zope.schema import TextLine, Text, Choice, Bool
 
 from pyams_skin import _
 
@@ -133,10 +133,42 @@
                       description=_("Public author name"),
                       required=False)
 
-    icon = ImageField(title="Icon",
+    icon = ImageField(title=_("Icon"),
                       description=_("Browser favourite icon"),
                       required=False)
 
     logo = ImageField(title=_("Logo"),
                       description=_("Image containing application logo"),
                       required=False)
+
+
+SKIN_BACK_CONFIGURATION_KEY = 'pyams_skin.back-office.configuration'
+
+
+class IBackOfficeConfiguration(IContained):
+    """Back-office configuration"""
+
+    title = TextLine(title=_("Title"),
+                     description=_("Application title visible in back-office"),
+                     required=False)
+
+    login_header = Text(title=_("Login header"),
+                        description=_("This reStructuredText text will be displayed in login page header"),
+                        required=False)
+
+    login_footer = Text(title=_("Login footer"),
+                        description=_("This reStructuredText text will be displayed in login page footer"),
+                        required=False)
+
+    icon = ImageField(title=_("Icon"),
+                      description=_("Browser favourite icon"),
+                      required=False)
+
+    logo = ImageField(title=_("Logo"),
+                      description=_("Image containing application logo"),
+                      required=False)
+
+    display_content_icon = Bool(title=_("Display title icon?"),
+                                description=_("Should icons be displayed into content's title area ?"),
+                                required=True,
+                                default=True)