# HG changeset patch # User Thierry Florac # Date 1528977811 -7200 # Node ID d093aba47072ddf75d21345b27404c55db763c37 # Parent bb371b8a67e4e814e4e567516e5b2c1ea88edc22 Added basic illustration component diff -r bb371b8a67e4 -r d093aba47072 src/pyams_content/component/illustration/__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) diff -r bb371b8a67e4 -r d093aba47072 src/pyams_content/component/illustration/interfaces/__init__.py --- 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' diff -r bb371b8a67e4 -r d093aba47072 src/pyams_content/component/illustration/zmi/__init__.py --- 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"""