Added basic illustration component
authorThierry Florac <thierry.florac@onf.fr>
Thu, 14 Jun 2018 14:03:31 +0200
changeset 682 d093aba47072
parent 681 bb371b8a67e4
child 683 20acd0a6d5a5
Added basic illustration component
src/pyams_content/component/illustration/__init__.py
src/pyams_content/component/illustration/interfaces/__init__.py
src/pyams_content/component/illustration/zmi/__init__.py
--- a/src/pyams_content/component/illustration/__init__.py	Thu Jun 14 10:40:46 2018 +0200
+++ b/src/pyams_content/component/illustration/__init__.py	Thu Jun 14 14:03:31 2018 +0200
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationTarget, \
-    ILLUSTRATION_KEY, ILLUSTRATION_RENDERERS
+    ILLUSTRATION_KEY, ILLUSTRATION_RENDERERS, IBasicIllustration, IBasicIllustrationTarget, BASIC_ILLUSTRATION_KEY
 from pyams_content.features.checker.interfaces import IContentChecker, MISSING_VALUE, MISSING_LANG_VALUE
 from pyams_file.interfaces import IFileInfo, IImage, IResponsiveImage
 from pyams_i18n.interfaces import INegotiator, II18n, II18nManager
@@ -46,17 +46,14 @@
 from pyams_content import _
 
 
-@implementer(IIllustration)
-@factory_config(provided=IIllustration)
-class Illustration(RenderedContentMixin, Persistent, Contained):
+@implementer(IBasicIllustration)
+@factory_config(provided=IBasicIllustration)
+class BasicIllustration(Persistent, Contained):
     """Illustration persistent class"""
 
     _data = I18nFileProperty(IIllustration['data'])
     title = FieldProperty(IIllustration['title'])
     alt_title = FieldProperty(IIllustration['alt_title'])
-    description = FieldProperty(IIllustration['description'])
-    author = FieldProperty(IIllustration['author'])
-    renderer = FieldProperty(IIllustration['renderer'])
 
     @property
     def data(self):
@@ -70,6 +67,28 @@
                 alsoProvides(data, IResponsiveImage)
 
 
+@adapter_config(context=IBasicIllustrationTarget, provides=IIllustration)
+def basic_illustration_factory(context):
+    """Basic illustration factory"""
+
+    def illustration_callback(illustration):
+        get_current_registry().notify(ObjectAddedEvent(illustration, context, illustration.__name__))
+
+    return get_annotation_adapter(context, BASIC_ILLUSTRATION_KEY, BasicIllustration,
+                                  name='++illustration++',
+                                  callback=illustration_callback)
+
+
+@implementer(IIllustration)
+@factory_config(provided=IIllustration)
+class Illustration(RenderedContentMixin, BasicIllustration):
+    """Illustration persistent class"""
+
+    description = FieldProperty(IIllustration['description'])
+    author = FieldProperty(IIllustration['author'])
+    renderer = FieldProperty(IIllustration['renderer'])
+
+
 @adapter_config(context=IIllustrationTarget, provides=IIllustration)
 def illustration_factory(context):
     """Illustration factory"""
@@ -95,21 +114,21 @@
             info.description = II18n(illustration).get_attribute('alt_title', lang, request)
 
 
-@subscriber(IObjectAddedEvent, context_selector=IIllustration)
+@subscriber(IObjectAddedEvent, context_selector=IBasicIllustration)
 def handle_added_illustration(event):
     """Handle added illustration"""
     illustration = event.object
     update_illustration_properties(illustration)
 
 
-@subscriber(IObjectModifiedEvent, context_selector=IIllustration)
+@subscriber(IObjectModifiedEvent, context_selector=IBasicIllustration)
 def handle_modified_illustration(event):
     """Handle modified illustration"""
     illustration = event.object
     update_illustration_properties(illustration)
 
 
-@adapter_config(name='illustration', context=IIllustrationTarget, provides=ITraversable)
+@adapter_config(name='illustration', context=IBasicIllustrationTarget, provides=ITraversable)
 class IllustrationNamespace(ContextAdapter):
     """++illustration++ namespace adapter"""
 
@@ -118,12 +137,14 @@
         return registry.queryAdapter(self.context, IIllustration, name=name)
 
 
-@adapter_config(name='illustration', context=IIllustrationTarget, provides=ISublocations)
+@adapter_config(name='illustration', context=IBasicIllustrationTarget, provides=ISublocations)
 class IllustrationSublocations(ContextAdapter):
     """Illustration sub-locations adapter"""
 
     def sublocations(self):
-        return IIllustration(self.context),
+        registry = get_global_registry()
+        for name, adapter in registry.getAdapters((self, ), IBasicIllustration):
+            yield adapter
 
 
 @adapter_config(context=IIllustration, provides=IContentChecker)
--- a/src/pyams_content/component/illustration/interfaces/__init__.py	Thu Jun 14 10:40:46 2018 +0200
+++ b/src/pyams_content/component/illustration/interfaces/__init__.py	Thu Jun 14 14:03:31 2018 +0200
@@ -22,6 +22,7 @@
 from zope.annotation.interfaces import IAttributeAnnotatable
 
 # import packages
+from zope.interface import Interface
 from zope.schema import Choice, TextLine
 
 from pyams_content import _
@@ -31,12 +32,14 @@
 # Illustration
 #
 
+BASIC_ILLUSTRATION_KEY = 'pyams_content.illustration.base'
+
 ILLUSTRATION_KEY = 'pyams_content.illustration'
 ILLUSTRATION_RENDERERS = 'PyAMS.illustration.renderers'
 
 
-class IIllustration(IRenderedContent):
-    """Illustration paragraph"""
+class IBasicIllustration(Interface):
+    """Basic illustration interface"""
 
     data = I18nThumbnailMediaField(title=_("Image or video data"),
                                    description=_("Image or video content"),
@@ -49,6 +52,10 @@
                                   description=_("Alternate title used to describe image content"),
                                   required=False)
 
+
+class IIllustration(IBasicIllustration, IRenderedContent):
+    """Illustration paragraph"""
+
     description = I18nTextField(title=_("Description"),
                                 description=_(""),
                                 required=False)
@@ -63,8 +70,12 @@
                       default='default')
 
 
-class IIllustrationTarget(IAttributeAnnotatable):
-    """Illustration target marker interface"""
+class IBasicIllustrationTarget(IAttributeAnnotatable):
+    """Basic illustration target marker interface"""
+
+
+class IIllustrationTarget(IBasicIllustrationTarget):
+    """Illustration target interface"""
 
 
 ILLUSTRATION_PARAGRAPH_TYPE = 'Illustration'
--- a/src/pyams_content/component/illustration/zmi/__init__.py	Thu Jun 14 10:40:46 2018 +0200
+++ b/src/pyams_content/component/illustration/zmi/__init__.py	Thu Jun 14 14:03:31 2018 +0200
@@ -16,7 +16,8 @@
 # import standard library
 
 # import interfaces
-from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationTarget
+from pyams_content.component.illustration.interfaces import IBasicIllustration, IBasicIllustrationTarget, \
+    IIllustration, IIllustrationTarget
 from pyams_content.component.paragraph import IBaseParagraph
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphContainerTable, IParagraphTitleToolbar
 from pyams_form.interfaces.form import IInnerSubForm, IWidgetsPrefixViewletsManager
@@ -64,10 +65,10 @@
         return ''
 
 
-@adapter_config(name='illustration', context=(IIllustrationTarget, IPyAMSLayer, IPropertiesEditForm),
+@adapter_config(name='illustration', context=(IBasicIllustrationTarget, IPyAMSLayer, IPropertiesEditForm),
                 provides=IInnerSubForm)
-class IllustrationPropertiesInnerEditForm(InnerAdminEditForm):
-    """Illustration properties inner edit form"""
+class BasicIllustrationPropertiesInnerEditForm(InnerAdminEditForm):
+    """Basic illustration properties inner edit form"""
 
     prefix = 'illustration_form.'
 
@@ -75,6 +76,43 @@
     padding_class = ''
     fieldset_class = 'margin-top-10 padding-y-5'
 
+    legend = _("Illustration")
+    legend_class = 'illustration switcher no-y-padding padding-right-10 pull-left width-auto'
+
+    fields = field.Fields(IBasicIllustration).omit('__parent__', '__name__')
+
+    weight = 10
+
+    def getContent(self):
+        return IIllustration(self.context)
+
+    def check_mode(self):
+        if self.parent_form is not None:
+            self.mode = self.parent_form.mode
+
+    @property
+    def switcher_state(self):
+        content = self.getContent()
+        for value in (content.data or {}).values():
+            if value:
+                return 'open'
+
+    def get_ajax_output(self, changes):
+        output = super(BasicIllustrationPropertiesInnerEditForm, self).get_ajax_output(changes)
+        updated = changes.get(IIllustration, ())
+        events = output.setdefault('events', [])
+        if 'data' in updated:
+            # we have to commit transaction to be able to handle blobs...
+            ITransactionManager(self.context).get().commit()
+            events.append(get_json_form_refresh_event(self.context, self.request, self.__class__))
+        return output
+
+
+@adapter_config(name='illustration', context=(IIllustrationTarget, IPyAMSLayer, IPropertiesEditForm),
+                provides=IInnerSubForm)
+class IllustrationPropertiesInnerEditForm(BasicIllustrationPropertiesInnerEditForm):
+    """Illustration properties inner edit form"""
+
     @property
     def legend(self):
         if IBaseParagraph.providedBy(self.context):
@@ -93,14 +131,6 @@
     fields['renderer'].widgetFactory = RendererFieldWidget
 
     hide_widgets_prefix_div = True
-    weight = 10
-
-    def getContent(self):
-        return IIllustration(self.context)
-
-    def check_mode(self):
-        if self.parent_form is not None:
-            self.mode = self.parent_form.mode
 
     def updateWidgets(self, prefix=None):
         super(IllustrationPropertiesInnerEditForm, self).updateWidgets(prefix)
@@ -112,10 +142,6 @@
         updated = changes.get(IIllustration, ())
         events = output.setdefault('events', [])
         if 'data' in updated:
-            # we have to commit transaction to be able to handle blobs...
-            ITransactionManager(self.context).get().commit()
-            events.append(get_json_form_refresh_event(self.context, self.request,
-                                                      IllustrationPropertiesInnerEditForm))
             if IBaseParagraph.providedBy(self.context):
                 if self.getContent().data:
                     events.append(get_json_paragraph_markers_refresh_event(self.context, self.request, self,
@@ -130,8 +156,8 @@
         return output
 
 
-@viewlet_config(name='illustration-thumbnail', context=IIllustrationTarget, layer=IPyAMSLayer,
-                view=IllustrationPropertiesInnerEditForm, manager=IWidgetsPrefixViewletsManager)
+@viewlet_config(name='illustration-thumbnail', context=IBasicIllustrationTarget, layer=IPyAMSLayer,
+                view=BasicIllustrationPropertiesInnerEditForm, manager=IWidgetsPrefixViewletsManager)
 @template_config(template='templates/illustration-thumbnail.pt', layer=IPyAMSLayer)
 class IllustrationThumbnail(Viewlet):
     """Paragraph illustration thumbnail"""