--- 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)