--- a/src/pyams_default_theme/component/paragraph/html.py Mon Sep 28 15:50:58 2020 +0200
+++ b/src/pyams_default_theme/component/paragraph/html.py Fri Nov 13 13:23:00 2020 +0100
@@ -11,18 +11,27 @@
#
from fanstatic import ConfigurationError
+from persistent import Persistent
+from zope.location import Location
+from zope.schema.fieldproperty import FieldProperty
from pyams_content.component.illustration import IIllustration
+from pyams_content.component.links import InternalReferenceMixin
from pyams_content.component.paragraph.interfaces.html import IHTMLParagraph, IRawParagraph
from pyams_content.features.renderer.interfaces import IContentRenderer
from pyams_default_theme import library
+from pyams_default_theme.component.paragraph.interfaces.html import \
+ IHTMLParagraphWithLogosRendererSettings
from pyams_default_theme.features.renderer import BaseContentRenderer
+from pyams_default_theme.shared.logo import DISABLED_LINK, INTERNAL_FIRST
from pyams_skin.layer import IPyAMSLayer
from pyams_template.template import template_config
from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.factory import factory_config
from pyams_utils.fanstatic import ExternalResource
from pyams_utils.interfaces.text import IHTMLRenderer
from pyams_utils.pygments import IPygmentsCodeConfiguration, render_source
+from pyams_utils.url import canonical_url, relative_url
__docformat__ = 'restructuredtext'
@@ -139,6 +148,7 @@
"""HTML paragraph default renderer"""
label = _("Default rich text renderer")
+ weight = 10
i18n_context_attrs = ('title', 'body',)
@@ -152,3 +162,69 @@
renderer = self.illustration_renderer = self.illustration.get_renderer(self.request)
if renderer is not None:
renderer.update()
+
+
+#
+# HTML paragraph renderer with logos
+#
+
+HTML_PARAGRAPH_WITH_LOGOS_RENDERER_SETTINGS_KEY = 'pyams_content.html.renderer:text-with-logos'
+
+
+@factory_config(IHTMLParagraphWithLogosRendererSettings)
+class HTMLParagraphWithLogosRendererSettings(Persistent, Location, InternalReferenceMixin):
+ """HTML paragraph with logos renderer settings"""
+
+ reference = FieldProperty(IHTMLParagraphWithLogosRendererSettings['reference'])
+ position = FieldProperty(IHTMLParagraphWithLogosRendererSettings['position'])
+ target_priority = FieldProperty(IHTMLParagraphWithLogosRendererSettings['target_priority'])
+ force_canonical_url = FieldProperty(IHTMLParagraphWithLogosRendererSettings['force_canonical_url'])
+
+
+@adapter_config(context=IHTMLParagraph, provides=IHTMLParagraphWithLogosRendererSettings)
+def html_paragraph_with_logos_renderer_settings_factory(context):
+ """HTML paragraph with logos renderer settings factory"""
+ return get_annotation_adapter(context, HTML_PARAGRAPH_WITH_LOGOS_RENDERER_SETTINGS_KEY,
+ IHTMLParagraphWithLogosRendererSettings)
+
+
+@adapter_config(name='text-with-logos',
+ context=(IHTMLParagraph, IPyAMSLayer),
+ provides=IContentRenderer)
+@template_config(template='templates/html-logos.pt', layer=IPyAMSLayer)
+class HTMLParagraphWithLogosRenderer(HTMLParagraphDefaultRenderer):
+ """HTML paragraph renderer with logos"""
+
+ label = _("Rich text renderer with logos")
+ weight = 20
+
+ settings_interface = IHTMLParagraphWithLogosRendererSettings
+
+ def get_internal_url(self, logo):
+ if logo is not None:
+ if self.settings.force_canonical_url:
+ url_getter = canonical_url
+ else:
+ url_getter = relative_url
+ return url_getter(logo, request=self.request)
+ return None
+
+ @staticmethod
+ def get_external_url(logo):
+ return logo.url
+
+ def get_logo_url(self):
+ priority = self.settings.target_priority
+ if priority == DISABLED_LINK:
+ return None
+ logo = self.settings.target
+ if logo is None:
+ return None
+ order = [self.get_external_url, self.get_internal_url]
+ if priority == INTERNAL_FIRST:
+ order = reversed(order)
+ for getter in order:
+ result = getter(logo)
+ if result is not None:
+ return result
+ return None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/component/paragraph/interfaces/html.py Fri Nov 13 13:23:00 2020 +0100
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2015-2020 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+"""PyAMS_default_theme.component module
+
+"""
+
+from zope.schema import Bool, Choice
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
+
+from pyams_content.shared.logo import LOGO_CONTENT_TYPE
+from pyams_default_theme.shared.logo.interfaces import EXTERNAL_FIRST, TARGET_PRIORITY_VOCABULARY
+from pyams_sequence.interfaces import IInternalReference
+from pyams_sequence.schema import InternalReferenceField
+
+
+__docformat__ = 'restructuredtext'
+
+from pyams_default_theme import _
+
+
+ABOVE_ALIGN = 'above'
+LEFT_ALIGN = 'left'
+RIGHT_ALIGN = 'right'
+BELOW_ALIGN = 'below'
+
+LOGO_POSITION = (
+ {'id': ABOVE_ALIGN, 'title': _("Centered above text")},
+ {'id': LEFT_ALIGN, 'title': _("Left aligned (default)")},
+ {'id': RIGHT_ALIGN, 'title': _("Right aligned")},
+ {'id': BELOW_ALIGN, 'title': _("Centered below text")}
+)
+
+LOGO_POSITION_VOCABULARY = SimpleVocabulary([SimpleTerm(item['id'], title=item['title'])
+ for item in LOGO_POSITION])
+
+
+class IHTMLParagraphWithLogosRendererSettings(IInternalReference):
+ """HTML paragraph with logos renderer settings interface"""
+
+ reference = InternalReferenceField(title=_("Selected logo"),
+ description=_("Selected logo. You can "
+ "search a reference using '+' followed by "
+ "internal number, of by entering text "
+ "matching content title."),
+ content_type=LOGO_CONTENT_TYPE,
+ required=True)
+
+ position = Choice(title=_("Logo position"),
+ required=True,
+ vocabulary=LOGO_POSITION_VOCABULARY,
+ default=LEFT_ALIGN)
+
+ target_priority = Choice(title=_("Links priority"),
+ description=_("Order in which internal and external links are "
+ "evaluated on logo"),
+ required=True,
+ vocabulary=TARGET_PRIORITY_VOCABULARY,
+ default=EXTERNAL_FIRST)
+
+ force_canonical_url = Bool(title=_("Force canonical URL"),
+ description=_("By default, internal links use a \"relative\" URL, "
+ "which tries to display link target in the current "
+ "context; by using a canonical URL, you can display "
+ "target in it's attachment context (if defined)"),
+ required=False,
+ default=False)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/component/paragraph/templates/html-logos.pt Fri Nov 13 13:23:00 2020 +0100
@@ -0,0 +1,83 @@
+<tal:var define="renderer view.illustration_renderer;
+ settings view.settings;
+ position getattr(renderer, 'position', None) if renderer is not None else None;"
+ switch="position">
+ <tal:var case="'before-title'">${structure:renderer.render()}</tal:var>
+ <h2 tal:define="title view.title"
+ tal:condition="title and (position != 'before-title')">${title}</h2>
+ <tal:var case="'before-body'">${structure:renderer.render()}</tal:var>
+ <tal:var define="logo settings.target"
+ switch="logo is None">
+ <tal:if case="True">
+ <div>${structure:tales:html(view.body, 'oid_to_href;glossary')}</div>
+ </tal:if>
+ <tal:if case="False">
+ <tal:select define="url view.get_logo_url()"
+ switch="settings.position">
+ <tal:if case="'above'">
+ <div class="row">
+ <div class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-4">
+ <a tal:omit-tag="not:url"
+ href="${url}" title="${logo.get_title(request)}">
+ ${structure:tales:picture(logo.image,
+ lg_width=2, md_width=2,
+ sm_width=8, xs_width=8)}
+ </a>
+ </div>
+ </div>
+ <div>
+ ${structure:tales:html(view.body, 'oid_to_href;glossary')}
+ </div>
+ </tal:if>
+ <tal:if case="'left'">
+ <div class="row">
+ <div class="col-xs-6 col-xs-offset-3 col-sm-3 col-sm-offset-0 col-md-2">
+ <a tal:omit-tag="not:url"
+ href="${url}" title="${logo.get_title(request)}">
+ ${structure:tales:picture(logo.image,
+ lg_width=2, md_width=2,
+ sm_width=2, xs_width=12)}
+ </a>
+ </div>
+ <div class="col-xs-12 col-sm-9 col-md-10">
+ ${structure:tales:html(view.body, 'oid_to_href;glossary')}
+ </div>
+ </div>
+ </tal:if>
+ <tal:if case="'right'">
+ <div class="row">
+ <div class="col-xs-12 col-sm-9 col-md-10">
+ ${structure:tales:html(view.body, 'oid_to_href;glossary')}
+ </div>
+ <div class="col-xs-6 col-xs-offset-3 col-sm-3 col-sm-offset-0 col-md-2">
+ <a tal:omit-tag="not:url"
+ href="${url}" title="${logo.get_title(request)}">
+ ${structure:tales:picture(logo.image,
+ lg_width=2, md_width=2,
+ sm_width=2, xs_width=12)}
+ </a>
+ </div>
+ </div>
+ </tal:if>
+ <tal:if case="'below'">
+ <div>
+ ${structure:tales:html(view.body, 'oid_to_href;glossary')}
+ </div>
+ <div class="row">
+ <div class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-4">
+ <a tal:omit-tag="not:url"
+ href="${url}" title="${logo.get_title(request)}">
+ ${structure:tales:picture(logo.image,
+ lg_width=2, md_width=2,
+ sm_width=8, xs_width=8)}
+ </a>
+ </div>
+ </div>
+ </tal:if>
+ </tal:select>
+ </tal:if>
+ </tal:var>
+ <tal:var case="'after-body'">${structure:renderer.render()}</tal:var>
+ <div class="clearfix"></div>
+ ${structure:provider:pyams.associations}
+</tal:var>