Refactored preview using "real" renderers
authorThierry Florac <thierry.florac@onf.fr>
Fri, 16 Mar 2018 08:17:54 +0100
changeset 487 093f201e3168
parent 486 cb67e71dafff
child 488 826448236ec9
Refactored preview using "real" renderers
src/pyams_content/component/association/zmi/paragraph.py
src/pyams_content/component/gallery/zmi/paragraph.py
src/pyams_content/component/illustration/zmi/paragraph.py
src/pyams_content/component/paragraph/interfaces/__init__.py
src/pyams_content/component/paragraph/zmi/contact.py
src/pyams_content/component/paragraph/zmi/frame.py
src/pyams_content/component/paragraph/zmi/header.py
src/pyams_content/component/paragraph/zmi/html.py
src/pyams_content/component/paragraph/zmi/keypoint.py
src/pyams_content/component/paragraph/zmi/milestone.py
src/pyams_content/component/paragraph/zmi/pictogram.py
src/pyams_content/component/paragraph/zmi/preview.py
src/pyams_content/component/paragraph/zmi/templates/html-preview.pt
src/pyams_content/component/paragraph/zmi/templates/html-render.pt
src/pyams_content/component/paragraph/zmi/templates/preview.pt
src/pyams_content/component/paragraph/zmi/templates/raw-preview.pt
src/pyams_content/component/paragraph/zmi/templates/raw-render.pt
src/pyams_content/component/paragraph/zmi/verbatim.py
src/pyams_content/component/paragraph/zmi/video.py
src/pyams_content/component/video/provider/zmi/__init__.py
src/pyams_content/component/video/provider/zmi/templates/dailymotion-preview.pt
src/pyams_content/component/video/provider/zmi/templates/dailymotion-render.pt
src/pyams_content/component/video/provider/zmi/templates/vimeo-preview.pt
src/pyams_content/component/video/provider/zmi/templates/vimeo-render.pt
src/pyams_content/component/video/provider/zmi/templates/youtube-preview.pt
src/pyams_content/component/video/provider/zmi/templates/youtube-render.pt
src/pyams_content/component/video/zmi/paragraph.py
src/pyams_content/component/video/zmi/templates/video-preview.pt
src/pyams_content/component/video/zmi/templates/video-render.pt
src/pyams_content/features/preview/zmi/__init__.py
src/pyams_content/features/preview/zmi/templates/preview.pt
src/pyams_content/features/renderer/zmi/__init__.py
src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo
src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po
src/pyams_content/locales/pyams_content.pot
src/pyams_content/root/__init__.py
src/pyams_content/shared/blog/manager.py
src/pyams_content/shared/form/zmi/preview.py
src/pyams_content/shared/form/zmi/render.py
src/pyams_content/shared/imagemap/zmi/paragraph.py
src/pyams_content/shared/imagemap/zmi/preview.py
src/pyams_content/shared/imagemap/zmi/render.py
src/pyams_content/shared/imagemap/zmi/templates/paragraph-preview.pt
src/pyams_content/shared/imagemap/zmi/templates/paragraph-render.pt
src/pyams_content/shared/imagemap/zmi/templates/preview.pt
src/pyams_content/shared/imagemap/zmi/templates/render.pt
src/pyams_content/shared/logo/zmi/paragraph.py
src/pyams_content/shared/site/folder.py
src/pyams_content/shared/site/manager.py
src/pyams_content/shared/view/zmi/preview.py
src/pyams_content/shared/view/zmi/render.py
src/pyams_content/shared/view/zmi/templates/preview.pt
src/pyams_content/shared/view/zmi/templates/render.pt
--- a/src/pyams_content/component/association/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/association/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -19,7 +19,7 @@
 from pyams_content.component.association.interfaces import IAssociationParagraph, ASSOCIATION_PARAGRAPH_TYPE
 from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
 from pyams_content.shared.common.interfaces import IWfSharedContent
@@ -33,7 +33,7 @@
 from pyams_content.component.association.paragraph import AssociationParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -150,9 +150,9 @@
 
 
 #
-# Association paragraph preview
+# Association paragraph renderer
 #
 
-@adapter_config(context=(IAssociationParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class AssociationParagraphPreview(BaseRenderedContentPreview):
-    """Association paragraph preview"""
+@adapter_config(context=(IAssociationParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class AssociationParagraphRenderer(BaseRenderedContentRenderer):
+    """Association paragraph renderer"""
--- a/src/pyams_content/component/gallery/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/gallery/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -19,7 +19,7 @@
 from pyams_content.component.gallery.interfaces import IGalleryParagraph, IBaseGallery, GALLERY_PARAGRAPH_TYPE
 from pyams_content.component.gallery.zmi.interfaces import IGalleryContentsView
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
 from pyams_form.interfaces.form import IInnerForm, IEditFormButtons, IInnerSubForm
@@ -33,7 +33,7 @@
 from pyams_content.component.gallery.paragraph import Gallery
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_content.shared.common.zmi import WfSharedContentPermissionMixin
 from pyams_pagelet.pagelet import pagelet_config
@@ -185,9 +185,9 @@
 
 
 #
-# Gallery paragraph preview
+# Gallery paragraph renderer
 #
 
-@adapter_config(context=(IGalleryParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class GalleryParagraphPreview(BaseRenderedContentPreview):
-    """Gallery preview"""
+@adapter_config(context=(IGalleryParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class GalleryParagraphRenderer(BaseRenderedContentRenderer):
+    """Gallery paragraph renderer"""
--- a/src/pyams_content/component/illustration/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/illustration/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, \
-    IParagraphContainer, IParagraphPreview
+    IParagraphContainer, IParagraphRenderer
 from pyams_content.component.illustration.interfaces import IIllustration, IIllustrationParagraph, \
     ILLUSTRATION_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
@@ -33,7 +33,7 @@
 from pyams_content.component.illustration.paragraph import Illustration
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -187,9 +187,9 @@
 
 
 #
-# Illustration preview
+# Illustration renderer
 #
 
-@adapter_config(context=(IIllustrationParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class IllustrationPreview(BaseRenderedContentPreview):
-    """Illustration preview"""
+@adapter_config(context=(IIllustrationParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class IllustrationRenderer(BaseRenderedContentRenderer):
+    """Illustration renderer"""
--- a/src/pyams_content/component/paragraph/interfaces/__init__.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/interfaces/__init__.py	Fri Mar 16 08:17:54 2018 +0100
@@ -87,7 +87,7 @@
                                    value_type=Choice(vocabulary='PyAMS paragraph factories'))
 
 
-class IParagraphPreview(IContentProvider):
-    """Paragraph preview renderer"""
+class IParagraphRenderer(IContentProvider):
+    """Paragraph renderer interface"""
 
     language = Attribute("Preview language")
--- a/src/pyams_content/component/paragraph/zmi/contact.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/contact.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IBaseParagraph, IParagraphPreview
+    IBaseParagraph, IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.contact import CONTACT_PARAGRAPH_TYPE, IContactParagraph
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphContainerView, IParagraphInnerEditor
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -32,7 +32,7 @@
 from pyams_content.component.paragraph.contact import ContactParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAddMenu, BaseParagraphAJAXAddForm, \
     BaseParagraphPropertiesEditForm, BaseParagraphAJAXEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -167,9 +167,9 @@
 
 
 #
-# Contact paragraph preview
+# Contact paragraph renderer
 #
 
-@adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class ContactParagraphPreview(BaseRenderedContentPreview):
-    """Contact paragraph preview"""
+@adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class ContactParagraphRenderer(BaseRenderedContentRenderer):
+    """Contact paragraph renderer"""
--- a/src/pyams_content/component/paragraph/zmi/frame.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/frame.py	Fri Mar 16 08:17:54 2018 +0100
@@ -19,7 +19,7 @@
 from pyams_content.component.association.interfaces import IAssociationTarget
 from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.frame import IFrameParagraph, FRAME_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -37,7 +37,7 @@
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
 from pyams_content.component.paragraph.zmi.container import ParagraphContainerTable, \
     ParagraphTitleToolbarViewletManager
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config, ContextRequestAdapter
@@ -224,9 +224,9 @@
 
 
 #
-# Framed text paragraph preview
+# Framed text paragraph renderer
 #
 
-@adapter_config(context=(IFrameParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class FrameParagraphPreview(BaseRenderedContentPreview):
-    """Framed text paragraph preview"""
+@adapter_config(context=(IFrameParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class FrameParagraphRenderer(BaseRenderedContentRenderer):
+    """Framed text paragraph renderer"""
--- a/src/pyams_content/component/paragraph/zmi/header.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/header.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.header import IHeaderParagraph, HEADER_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -31,7 +31,7 @@
 from pyams_content.component.paragraph.header import HeaderParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -169,9 +169,9 @@
 
 
 #
-# Header paragraph preview
+# Header paragraph renderer
 #
 
-@adapter_config(context=(IHeaderParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class HeaderParagraphPreview(BaseRenderedContentPreview):
-    """Header paragraph preview"""
+@adapter_config(context=(IHeaderParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class HeaderParagraphRenderer(BaseRenderedContentRenderer):
+    """Header paragraph renderer"""
--- a/src/pyams_content/component/paragraph/zmi/html.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/html.py	Fri Mar 16 08:17:54 2018 +0100
@@ -20,7 +20,7 @@
 from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
 from pyams_content.component.illustration.interfaces import IIllustration
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphFactorySettings, \
-    IParagraphContainer, IParagraphPreview
+    IParagraphContainer, IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.html import IHTMLParagraph, IRawParagraph, RAW_PARAGRAPH_TYPE, \
     HTML_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
@@ -160,13 +160,13 @@
 
 
 #
-# Raw HTML paragraph preview
+# Raw HTML paragraph renderer
 #
 
-@adapter_config(context=(IRawParagraph, IPyAMSLayer), provides=IParagraphPreview)
-@template_config(template='templates/raw-preview.pt', layer=IPyAMSLayer)
-class RawParagraphPreview(BaseContentProvider):
-    """Raw HTML paragraph preview"""
+@adapter_config(context=(IRawParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+@template_config(template='templates/raw-render.pt', layer=IPyAMSLayer)
+class RawParagraphRenderer(BaseContentProvider):
+    """Raw HTML paragraph renderer"""
 
     language = None
 
@@ -340,13 +340,13 @@
 
 
 #
-# Rich text paragraph preview
+# Rich text paragraph renderer
 #
 
-@adapter_config(context=(IHTMLParagraph, IPyAMSLayer), provides=IParagraphPreview)
-@template_config(template='templates/html-preview.pt', layer=IPyAMSLayer)
-class HTMLParagraphPreview(BaseContentProvider):
-    """Rich text paragraph preview"""
+@adapter_config(context=(IHTMLParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+@template_config(template='templates/html-render.pt', layer=IPyAMSLayer)
+class HTMLParagraphRenderer(BaseContentProvider):
+    """Rich text paragraph renderer"""
 
     illustration = None
     illustration_renderer = None
--- a/src/pyams_content/component/paragraph/zmi/keypoint.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/keypoint.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.keypoint import IKeypointsParagraph, KEYPOINTS_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -31,7 +31,7 @@
 from pyams_content.component.paragraph.keypoint import KeypointsParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -169,9 +169,9 @@
 
 
 #
-# Key points paragraph preview
+# Key points paragraph renderer
 #
 
-@adapter_config(context=(IKeypointsParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class KeypointsParagraphPreview(BaseRenderedContentPreview):
-    """Key points paragraph preview"""
+@adapter_config(context=(IKeypointsParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class KeypointsParagraphRenderer(BaseRenderedContentRenderer):
+    """Key points paragraph renderer"""
--- a/src/pyams_content/component/paragraph/zmi/milestone.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/milestone.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,7 +18,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.milestone import MILESTONE_PARAGRAPH_TYPE, IMilestoneParagraph, \
     IMilestoneContainer, IMilestoneContainerTarget, IMilestone
 from pyams_content.component.paragraph.zmi import IParagraphContainerView
@@ -37,7 +37,7 @@
 from pyams_content.component.paragraph.milestone import MilestoneParagraph, Milestone
 from pyams_content.component.paragraph.zmi import BaseParagraphAddMenu, BaseParagraphAJAXAddForm, \
     BaseParagraphPropertiesEditForm, BaseParagraphAJAXEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_content.skin import pyams_content
 from pyams_form.form import AJAXAddForm, AJAXEditForm
@@ -174,12 +174,12 @@
 
 
 #
-# Milestone paragraph preview
+# Milestone paragraph renderer
 #
 
-@adapter_config(context=(IMilestoneParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class MilestoneParagraphPreview(BaseRenderedContentPreview):
-    """Milestone paragraph preview"""
+@adapter_config(context=(IMilestoneParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class MilestoneParagraphRenderer(BaseRenderedContentRenderer):
+    """Milestone paragraph renderer"""
 
 
 #
--- a/src/pyams_content/component/paragraph/zmi/pictogram.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/pictogram.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,7 +18,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.pictogram import PICTOGRAM_PARAGRAPH_TYPE, IPictogramParagraph, \
     IPictogramContainer, IPictogramContainerTarget, IPictogramItem
 from pyams_content.component.paragraph.zmi import IParagraphContainerView
@@ -38,7 +38,7 @@
 from pyams_content.component.paragraph.pictogram import PictogramParagraph, PictogramItem
 from pyams_content.component.paragraph.zmi import BaseParagraphAddMenu, BaseParagraphAJAXAddForm, \
     BaseParagraphPropertiesEditForm, BaseParagraphAJAXEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_content.skin import pyams_content
 from pyams_form.form import AJAXAddForm, AJAXEditForm
@@ -176,12 +176,12 @@
 
 
 #
-# Pictogram paragraph preview
+# Pictogram paragraph renderer
 #
 
-@adapter_config(context=(IPictogramParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class PictogramParagraphPreview(BaseRenderedContentPreview):
-    """Pictogram paragraph preview"""
+@adapter_config(context=(IPictogramParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class PictogramParagraphRenderer(BaseRenderedContentRenderer):
+    """Pictogram paragraph renderer"""
 
 
 #
--- a/src/pyams_content/component/paragraph/zmi/preview.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/preview.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,47 +17,39 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
-from pyams_content.features.preview.zmi.interfaces import IPreviewForm
-from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager
-from pyams_i18n.interfaces import II18nManager
-from pyams_skin.interfaces import IUserSkinnable
+    IParagraphRenderer
+from pyams_content.features.renderer.interfaces import IContentRenderer
 from pyams_skin.layer import IPyAMSLayer
-from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
 
 # import packages
-from pyams_skin.skin import apply_skin
-from pyams_template.template import template_config
-from pyams_utils.request import copy_request
-from pyams_viewlet.viewlet import viewlet_config, Viewlet
-from pyramid.decorator import reify
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_utils.adapter import adapter_config
 
 
-@viewlet_config(name='paragraphs-preview', context=IParagraphContainerTarget, layer=IPyAMSLayer,
-                view=IPreviewForm, manager=IWidgetsSuffixViewletsManager,
-                permission=VIEW_SYSTEM_PERMISSION, weight=100)
-@template_config(template='templates/preview.pt', layer=IPyAMSLayer)
-class ParagraphsContainerPreview(Viewlet):
-    """Paragraphs container preview"""
+@adapter_config(name='paragraphs-render', context=(IParagraphContainerTarget, IPyAMSLayer),
+                provides=IContentRenderer)
+class ParagraphsContainerRenderer(BaseContentRenderer):
+    """Paragraphs container renderer"""
+
+    weight = 10
 
-    def __init__(self, context, request, view, manager):
-        super(ParagraphsContainerPreview, self).__init__(context, request, view, manager)
-        self.paragraphs = [para for para in IParagraphContainer(self.context).values()
-                           if para.visible]
-        self.languages = II18nManager(self.context).get_languages()
+    def __init__(self, context, request):
+        super(ParagraphsContainerRenderer, self).__init__(context, request)
+        paragraphs = [para for para in IParagraphContainer(self.context).values()
+                      if para.visible]
+        self.renderers = [self.request.registry.queryMultiAdapter((paragraph, self.request), IParagraphRenderer)
+                          for paragraph in paragraphs]
 
-    @reify
-    def render_request(self):
-        request = copy_request(self.request)
-        root = self.request.root
-        skin = IUserSkinnable(root).get_skin()
-        if skin is not None:
-            apply_skin(request, skin)
-        return request
+    def update(self):
+        super(ParagraphsContainerRenderer, self).update()
+        for renderer in self.renderers:
+            if renderer is not None:
+                renderer.language = self.language
+                renderer.update()
 
-    def render_paragraph(self, paragraph, language=None):
-        preview = self.request.registry.queryMultiAdapter((paragraph, self.render_request), IParagraphPreview)
-        if preview is not None:
-            preview.language = language
-            preview.update()
-            return preview.render()
+    def render(self):
+        result = ''
+        for renderer in self.renderers:
+            if renderer is not None:
+                result += renderer.render()
+        return result
--- a/src/pyams_content/component/paragraph/zmi/templates/html-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<h3 tal:content="view.title">title</h3>
-<div tal:content="structure view.body">body</div>
-<tal:var content="structure view.render_illustration()">Illustration</tal:var>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/paragraph/zmi/templates/html-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,3 @@
+<h3 tal:content="view.title">title</h3>
+<div tal:content="structure view.body">body</div>
+<tal:var content="structure view.render_illustration()">Illustration</tal:var>
--- a/src/pyams_content/component/paragraph/zmi/templates/preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-<tal:var define="langs view.languages" i18n:domain="pyams_content">
-	<tal:if condition="len(langs) == 1">
-		<div class="margin-top-10">
-			<tal:loop repeat="paragraph view.paragraphs"
-					  replace="structure view.render_paragraph(paragraph)" />
-			<p tal:condition="not:view.paragraphs"
-			   i18n:translate="">This content doesn't contain any paragraph.</p>
-		</div>
-	</tal:if>
-	<tal:if condition="len(langs) > 1">
-		<ul class="nav nav-tabs margin-top-10">
-			<tal:loop repeat="lang langs">
-				<li tal:define="active python:'active' if repeat['lang'].start() else ''"
-					tal:attributes="class string:small ${active}">
-					<a data-toggle="tab" class="xsmall"
-					   tal:attributes="href string:#paragraphs-${lang}">
-						<img tal:attributes="src string:/--static--/pyams_i18n/img/flags/${lang}.png" />
-					</a>
-				</li>
-			</tal:loop>
-		</ul>
-		<div class="tab-content i18n-content bordered nohover">
-			<tal:loop repeat="lang langs">
-				<div tal:define="active python:'active' if repeat['lang'].start() else ''"
-					 tal:attributes="class string:clearfix tab-pane ${active} fade in padding-5;
-									 id string:paragraphs-${lang};">
-					<tal:loop repeat="paragraph view.paragraphs"
-							  replace="structure view.render_paragraph(paragraph, lang)" />
-					<p tal:condition="not:view.paragraphs"
-					   i18n:translate="">This content doesn't contain any paragraph.</p>
-				</div>
-			</tal:loop>
-		</div>
-	</tal:if>
-</tal:var>
--- a/src/pyams_content/component/paragraph/zmi/templates/raw-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<h3 tal:content="view.title">title</h3>
-<div tal:content="structure view.body">body</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/paragraph/zmi/templates/raw-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,2 @@
+<h3 tal:content="view.title">title</h3>
+<div tal:content="structure view.body">body</div>
--- a/src/pyams_content/component/paragraph/zmi/verbatim.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/verbatim.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,7 +18,7 @@
 # import interfaces
 from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.verbatim import IVerbatimParagraph, VERBATIM_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -32,7 +32,7 @@
 from pyams_content.component.paragraph.verbatim import VerbatimParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_utils.adapter import adapter_config
@@ -156,9 +156,9 @@
 
 
 #
-# Verbatim paragraph preview
+# Verbatim paragraph renderer
 #
 
-@adapter_config(context=(IVerbatimParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class VerbatimParagraphPreview(BaseRenderedContentPreview):
-    """Verbatim paragraph preview"""
+@adapter_config(context=(IVerbatimParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class VerbatimParagraphRenderer(BaseRenderedContentRenderer):
+    """Verbatim paragraph renderer"""
--- a/src/pyams_content/component/paragraph/zmi/video.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/paragraph/zmi/video.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,7 +18,7 @@
 # import interfaces
 from pyams_content.component.association.zmi.interfaces import IAssociationsParentForm
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.interfaces.video import IVideoParagraph, VIDEO_PARAGRAPH_TYPE
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
@@ -34,7 +34,7 @@
 from pyams_content.component.paragraph.video import VideoParagraph
 from pyams_content.component.paragraph.zmi import BaseParagraphAJAXAddForm, BaseParagraphAJAXEditForm, \
     BaseParagraphAddMenu, BaseParagraphPropertiesEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_form.group import NamedWidgetsGroup
 from pyams_pagelet.pagelet import pagelet_config
@@ -205,9 +205,9 @@
 
 
 #
-# Video paragraph preview
+# Video paragraph renderer
 #
 
-@adapter_config(context=(IVideoParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class VideoParagraphPreview(BaseRenderedContentPreview):
-    """Video paragraph preview"""
+@adapter_config(context=(IVideoParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class VideoParagraphRenderer(BaseRenderedContentRenderer):
+    """Video paragraph renderer"""
--- a/src/pyams_content/component/video/provider/zmi/__init__.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/video/provider/zmi/__init__.py	Fri Mar 16 08:17:54 2018 +0100
@@ -87,7 +87,7 @@
 
 
 @adapter_config(context=(YoutubeVideoSettings, IPyAMSLayer), provides=IExternalVideoRenderer)
-@template_config(template='templates/youtube-preview.pt', layer=IPyAMSLayer)
+@template_config(template='templates/youtube-render.pt', layer=IPyAMSLayer)
 class YoutubeVideoRenderer(BaseExternalVideoRenderer):
     """Youtube video renderer"""
 
@@ -95,7 +95,7 @@
 
 
 @adapter_config(context=(DailymotionVideoSettings, IPyAMSLayer), provides=IExternalVideoRenderer)
-@template_config(template='templates/dailymotion-preview.pt', layer=IPyAMSLayer)
+@template_config(template='templates/dailymotion-render.pt', layer=IPyAMSLayer)
 class DailymotionVideoRenderer(BaseExternalVideoRenderer):
     """Dailymotion video renderer"""
 
@@ -103,7 +103,7 @@
 
 
 @adapter_config(context=(VimeoVideoSettings, IPyAMSLayer), provides=IExternalVideoRenderer)
-@template_config(template='templates/vimeo-preview.pt', layer=IPyAMSLayer)
+@template_config(template='templates/vimeo-render.pt', layer=IPyAMSLayer)
 class VimeoVideoRenderer(BaseExternalVideoRenderer):
     """Vimeo video renderer"""
 
--- a/src/pyams_content/component/video/provider/zmi/templates/dailymotion-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<div class="video-wrapper">
-	<iframe type="text/html" class="video" frameborder="0"
-			tal:attributes="src string:https://www.dailymotion.com/embed/video/${context.video_id}?${view.get_url_params()};
-							width context.width;
-							height context.height;
-							allowfullscreen 'true' if context.allow_fullscreen else None;
-							allow 'autoplay' if context.autoplay else None;"></iframe>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/video/provider/zmi/templates/dailymotion-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,8 @@
+<div class="video-wrapper">
+	<iframe type="text/html" class="video" frameborder="0"
+			tal:attributes="src string:https://www.dailymotion.com/embed/video/${context.video_id}?${view.get_url_params()};
+							width context.width;
+							height context.height;
+							allowfullscreen 'true' if context.allow_fullscreen else None;
+							allow 'autoplay' if context.autoplay else None;"></iframe>
+</div>
--- a/src/pyams_content/component/video/provider/zmi/templates/vimeo-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<div class="video-wrapper">
-	<iframe type="text/html" class="video" frameborder="0"
-			tal:attributes="src string:https://player.vimeo.com/video/${context.video_id}?${view.get_url_params()};
-							width context.width;
-							height context.height;
-							allowfullscreen 'true' if context.allow_fullscreen else None;
-							webkitallowfullscreen 'true' if context.allow_fullscreen else None;
-							mozallowfullscreen 'true' if context.allow_fullscreen else None;"></iframe>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/video/provider/zmi/templates/vimeo-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,9 @@
+<div class="video-wrapper">
+	<iframe type="text/html" class="video" frameborder="0"
+			tal:attributes="src string:https://player.vimeo.com/video/${context.video_id}?${view.get_url_params()};
+							width context.width;
+							height context.height;
+							allowfullscreen 'true' if context.allow_fullscreen else None;
+							webkitallowfullscreen 'true' if context.allow_fullscreen else None;
+							mozallowfullscreen 'true' if context.allow_fullscreen else None;"></iframe>
+</div>
--- a/src/pyams_content/component/video/provider/zmi/templates/youtube-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<div class="video-wrapper">
-	<iframe type="text/html" class="video" frameborder="0"
-			tal:attributes="src string:https://www.youtube.com/embed/${context.video_id}?${view.get_url_params()};
-							width context.width;
-							height context.height;
-							allowfullscreen 'allowfullscreen' if context.allow_fullscreen else None;"></iframe>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/video/provider/zmi/templates/youtube-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,7 @@
+<div class="video-wrapper">
+	<iframe type="text/html" class="video" frameborder="0"
+			tal:attributes="src string:https://www.youtube.com/embed/${context.video_id}?${view.get_url_params()};
+							width context.width;
+							height context.height;
+							allowfullscreen 'allowfullscreen' if context.allow_fullscreen else None;"></iframe>
+</div>
--- a/src/pyams_content/component/video/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/component/video/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IBaseParagraph, IParagraphPreview
+    IBaseParagraph, IParagraphRenderer
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphContainerView, IParagraphInnerEditor
 from pyams_content.component.video.interfaces import IExternalVideoProvider, IExternalVideoSettings, \
     IExternalVideoParagraph, IExternalVideoRenderer, EXTERNAL_VIDEO_PARAGRAPH_TYPE
@@ -256,18 +256,18 @@
 
 
 #
-# Video paragraph preview
+# Video paragraph renderer
 #
 
-@adapter_config(context=(IExternalVideoParagraph, IPyAMSLayer), provides=IParagraphPreview)
-@template_config(template='templates/video-preview.pt', layer=IPyAMSLayer)
-class ExternalVideoParagraphPreview(BaseContentProvider):
-    """External video paragraph preview"""
+@adapter_config(context=(IExternalVideoParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+@template_config(template='templates/video-render.pt', layer=IPyAMSLayer)
+class ExternalVideoParagraphRenderer(BaseContentProvider):
+    """External video paragraph renderer"""
 
     video_renderer = None
 
     def __init__(self, context, request):
-        super(ExternalVideoParagraphPreview, self).__init__(context, request)
+        super(ExternalVideoParagraphRenderer, self).__init__(context, request)
         provider = context.get_provider()
         if provider is not None:
             registry = get_current_registry()
--- a/src/pyams_content/component/video/zmi/templates/video-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<h3 tal:condition="view.title"
-	tal:content="view.title">title</h3>
-<div tal:condition="view.body"
-	 tal:content="structure view.body">body</div>
-<div tal:condition="view.description"
-	 tal:content="structure extension:html(view.description)">Description</div>
-<tal:var replace="structure view.render_video()" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/component/video/zmi/templates/video-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,7 @@
+<h3 tal:condition="view.title"
+	tal:content="view.title">title</h3>
+<div tal:condition="view.body"
+	 tal:content="structure view.body">body</div>
+<div tal:condition="view.description"
+	 tal:content="structure extension:html(view.description)">Description</div>
+<tal:var replace="structure view.render_video()" />
--- a/src/pyams_content/features/preview/zmi/__init__.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/features/preview/zmi/__init__.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,6 +18,7 @@
 # import interfaces
 from pyams_content.features.preview.interfaces import IPreviewTarget
 from pyams_content.features.preview.zmi.interfaces import IPreviewForm
+from pyams_i18n.interfaces import II18nManager, INegotiator
 from pyams_skin.interfaces.viewlet import IToolbarViewletManager
 from pyams_skin.layer import IPyAMSLayer
 from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
@@ -26,6 +27,8 @@
 # import packages
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_skin.viewlet.toolbar import ToolbarAction
+from pyams_template.template import template_config
+from pyams_utils.registry import get_utility
 from pyams_viewlet.viewlet import viewlet_config
 from pyams_zmi.form import AdminDialogDisplayForm
 from z3c.form import field
@@ -45,16 +48,35 @@
     label_css_class = 'fa fa-newspaper-o'
     css_class = 'btn btn-xs btn-default'
 
-    url = 'preview.html'
+    url = 'content-preview.html'
     modal_target = True
 
 
-@pagelet_config(name='preview.html', context=IPreviewTarget, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+@pagelet_config(name='content-preview.html', context=IPreviewTarget, layer=IPyAMSLayer,
+                permission=VIEW_SYSTEM_PERMISSION)
+@template_config(template='templates/preview.pt', layer=IPyAMSLayer)
 @implementer(IPreviewForm)
 class PreviewForm(AdminDialogDisplayForm):
     """Content preview form"""
 
     legend = _("Content preview")
+
+    @property
+    def title(self):
+        translate = self.request.localizer.translate
+        return translate(_("{title} ({preview})")).format(title=super(PreviewForm, self).title,
+                                                          preview=translate(_("preview")))
+
     dialog_class = 'modal-max'
 
     fields = field.Fields(Interface)
+    languages = None
+
+    def __init__(self, context, request):
+        super(PreviewForm, self).__init__(context, request)
+        i18n = II18nManager(context, None)
+        if i18n is not None:
+            self.languages = i18n.get_languages()
+        else:
+            negotiator = get_utility(INegotiator)
+            self.languages = (negotiator.server_language, )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/features/preview/zmi/templates/preview.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,58 @@
+<div class="modal-dialog modal-medium"
+	 style="height: calc(100% - 50px);"
+	 tal:attributes="class string:modal-dialog ${view.dialog_class}">
+	<div class="modal-content">
+		<div class="modal-header"
+			 tal:define="header provider:form_header">
+			<tal:if condition="header">
+				<tal:var replace="structure header" />
+			</tal:if>
+			<tal:if condition="not:header">
+				<button type="button" class="close" data-dismiss="modal" aria-hidden="true"
+						tal:condition="view.is_dialog">
+					<i class="fa fa-fw fa-times-circle"></i>
+				</button>
+				<h3 class="modal-title"
+					tal:define="config extension:configuration;">
+					<span class="title" tal:content="view.title | context.title | config.title">Title</span>
+				</h3>
+				<tal:var replace="structure provider:form_toolbar" />
+			</tal:if>
+		</div>
+		<div class="modal-body no-padding">
+			<tal:var define="langs view.languages" i18n:domain="pyams_content">
+				<tal:if condition="len(langs) == 1">
+					<div class="margin-top-10">
+						<iframe src="preview.html" frameborder="0" style="width: 100%;"
+								tal:attributes="src string:preview.html?lang=${langs[0]}"
+								onload="this.style.height = (jQuery(parent.window).height() - 150) + 'px'"></iframe>
+					</div>
+				</tal:if>
+				<tal:if condition="len(langs) > 1">
+					<ul class="nav nav-tabs margin-top-10">
+						<tal:loop repeat="lang langs">
+							<li tal:define="active python:'active' if repeat['lang'].start() else ''"
+								tal:attributes="class string:small ${active}">
+								<a data-toggle="tab" class="xsmall"
+								   tal:attributes="href string:#preview-${lang}">
+									<img tal:attributes="src string:/--static--/pyams_i18n/img/flags/${lang}.png" />
+								</a>
+							</li>
+						</tal:loop>
+					</ul>
+					<div class="tab-content i18n-content bordered nohover">
+						<tal:loop repeat="lang langs">
+							<div tal:define="active python:'active' if repeat['lang'].start() else ''"
+								 tal:attributes="class string:clearfix tab-pane ${active} fade in padding-5;
+												 id string:preview-${lang};">
+								<iframe src="preview.html" frameborder="0" style="width: 100%;"
+										tal:attributes="src string:preview.html?lang=${lang}"
+										onload="this.style.height = (jQuery(parent.window).height() - 150) + 'px'"></iframe>
+							</div>
+						</tal:loop>
+					</div>
+				</tal:if>
+			</tal:var>
+		</div>
+	</div>
+</div>
--- a/src/pyams_content/features/renderer/zmi/__init__.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/features/renderer/zmi/__init__.py	Fri Mar 16 08:17:54 2018 +0100
@@ -37,16 +37,16 @@
 
 
 #
-# Base rendered content preview
+# Base rendered content renderer
 #
 
-class BaseRenderedContentPreview(BaseContentProvider):
-    """Base renderer preview"""
+class BaseRenderedContentRenderer(BaseContentProvider):
+    """Base content renderer"""
 
     language = None
 
     def __init__(self, context, request):
-        super(BaseRenderedContentPreview, self).__init__(context, request)
+        super(BaseRenderedContentRenderer, self).__init__(context, request)
         self.renderer = self.context.get_renderer()
 
     def update(self):
Binary file src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.mo has changed
--- a/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/locales/fr/LC_MESSAGES/pyams_content.po	Fri Mar 16 08:17:54 2018 +0100
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-03-14 09:14+0100\n"
+"POT-Creation-Date: 2018-03-15 12:04+0100\n"
 "PO-Revision-Date: 2015-09-10 10:42+0200\n"
 "Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
 "Language-Team: French\n"
@@ -833,12 +833,12 @@
 msgid "Add new pictogram"
 msgstr "Ajout d'un pictogramme"
 
-#: src/pyams_content/component/paragraph/zmi/pictogram.py:450
+#: src/pyams_content/component/paragraph/zmi/pictogram.py:455
 #: src/pyams_content/reference/pictograms/zmi/__init__.py:94
 msgid "Edit pictogram properties"
 msgstr "Propriétés du pictogramme"
 
-#: src/pyams_content/component/paragraph/zmi/pictogram.py:434
+#: src/pyams_content/component/paragraph/zmi/pictogram.py:439
 msgid "Pictogram was correctly added"
 msgstr "Le pictogramme a été ajouté."
 
@@ -914,11 +914,6 @@
 msgid "Edit header paragraph properties"
 msgstr "Propriétés du chapô"
 
-#: src/pyams_content/component/paragraph/zmi/templates/preview.pt:7
-#: src/pyams_content/component/paragraph/zmi/templates/preview.pt:30
-msgid "This content doesn't contain any paragraph."
-msgstr "Aucun paragraphe n'est associé à ce contenu."
-
 #: src/pyams_content/component/paragraph/interfaces/milestone.py:41
 #: src/pyams_content/component/paragraph/interfaces/__init__.py:43
 #: src/pyams_content/component/paragraph/interfaces/pictogram.py:42
@@ -3283,13 +3278,14 @@
 "automatiquement sélectionnés"
 
 #: src/pyams_content/shared/view/interfaces/__init__.py:61
-#: src/pyams_content/root/zmi/search.py:148
-msgid "Content types"
-msgstr "Types de contenus"
+msgid "Other content types"
+msgstr "Autres types de contenus"
 
 #: src/pyams_content/shared/view/interfaces/__init__.py:62
 msgid "Selected content types; leave empty for all"
-msgstr "Types de contenus sélectionnés ; laisser vide pour tous"
+msgstr ""
+"Autres types de contenus sélectionnés ; si l'on n'extrait pas le type du "
+"contexte et si cette sélection est vide, tous les types seront pris en charge"
 
 #: src/pyams_content/shared/view/interfaces/__init__.py:69
 msgid "Order by"
@@ -3753,6 +3749,10 @@
 msgid "Given site name doesn't exist!"
 msgstr "Le nom de site indiqué n'existe pas !"
 
+#: src/pyams_content/root/zmi/search.py:148
+msgid "Content types"
+msgstr "Types de contenus"
+
 #: src/pyams_content/root/zmi/__init__.py:77
 msgid "Home"
 msgstr "Accueil"
@@ -4241,11 +4241,11 @@
 msgid "{0}:"
 msgstr "{0} :"
 
-#: src/pyams_content/features/preview/zmi/__init__.py:42
+#: src/pyams_content/features/preview/zmi/__init__.py:45
 msgid "Preview"
 msgstr "Aperçu"
 
-#: src/pyams_content/features/preview/zmi/__init__.py:57
+#: src/pyams_content/features/preview/zmi/__init__.py:62
 msgid "Content preview"
 msgstr "Aperçu du contenu"
 
@@ -4445,6 +4445,9 @@
 msgid "Thank you."
 msgstr "Merci."
 
+#~ msgid "This content doesn't contain any paragraph."
+#~ msgstr "Aucun paragraphe n'est associé à ce contenu."
+
 #~ msgid ""
 #~ "This form allows you to select pictograms which will be available for "
 #~ "selection into your shared contents."
--- a/src/pyams_content/locales/pyams_content.pot	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/locales/pyams_content.pot	Fri Mar 16 08:17:54 2018 +0100
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-03-14 09:14+0100\n"
+"POT-Creation-Date: 2018-03-15 12:04+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -794,12 +794,12 @@
 msgid "Add new pictogram"
 msgstr ""
 
-#: ./src/pyams_content/component/paragraph/zmi/pictogram.py:450
+#: ./src/pyams_content/component/paragraph/zmi/pictogram.py:455
 #: ./src/pyams_content/reference/pictograms/zmi/__init__.py:94
 msgid "Edit pictogram properties"
 msgstr ""
 
-#: ./src/pyams_content/component/paragraph/zmi/pictogram.py:434
+#: ./src/pyams_content/component/paragraph/zmi/pictogram.py:439
 msgid "Pictogram was correctly added"
 msgstr ""
 
@@ -875,11 +875,6 @@
 msgid "Edit header paragraph properties"
 msgstr ""
 
-#: ./src/pyams_content/component/paragraph/zmi/templates/preview.pt:7
-#: ./src/pyams_content/component/paragraph/zmi/templates/preview.pt:30
-msgid "This content doesn't contain any paragraph."
-msgstr ""
-
 #: ./src/pyams_content/component/paragraph/interfaces/milestone.py:41
 #: ./src/pyams_content/component/paragraph/interfaces/__init__.py:43
 #: ./src/pyams_content/component/paragraph/interfaces/pictogram.py:42
@@ -3096,8 +3091,7 @@
 msgstr ""
 
 #: ./src/pyams_content/shared/view/interfaces/__init__.py:61
-#: ./src/pyams_content/root/zmi/search.py:148
-msgid "Content types"
+msgid "Other content types"
 msgstr ""
 
 #: ./src/pyams_content/shared/view/interfaces/__init__.py:62
@@ -3556,6 +3550,10 @@
 msgid "Given site name doesn't exist!"
 msgstr ""
 
+#: ./src/pyams_content/root/zmi/search.py:148
+msgid "Content types"
+msgstr ""
+
 #: ./src/pyams_content/root/zmi/__init__.py:77
 msgid "Home"
 msgstr ""
@@ -4037,11 +4035,11 @@
 msgid "{0}:"
 msgstr ""
 
-#: ./src/pyams_content/features/preview/zmi/__init__.py:42
+#: ./src/pyams_content/features/preview/zmi/__init__.py:45
 msgid "Preview"
 msgstr ""
 
-#: ./src/pyams_content/features/preview/zmi/__init__.py:57
+#: ./src/pyams_content/features/preview/zmi/__init__.py:62
 msgid "Content preview"
 msgstr ""
 
--- a/src/pyams_content/root/__init__.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/root/__init__.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,6 +18,7 @@
 # import standard library
 
 # import interfaces
+from pyams_content.features.preview.interfaces import IPreviewTarget
 from pyams_content.interfaces import WEBMASTER_ROLE, OPERATOR_ROLE
 from pyams_content.root.interfaces import ISiteRootRoles, ISiteRootConfiguration, ISiteRoot, \
     ISiteRootToolsConfiguration, ISiteRootBackOfficeConfiguration
@@ -42,7 +43,7 @@
 from zope.interface import implementer
 
 
-@implementer(IDefaultProtectionPolicy, ISiteRoot, ISiteRootRoles, IPortalContext)
+@implementer(IDefaultProtectionPolicy, ISiteRoot, ISiteRootRoles, IPortalContext, IPreviewTarget)
 class SiteRoot(ProtectedObject, BaseSiteRoot, UserSkinnableContent):
     """Main site root"""
 
--- a/src/pyams_content/shared/blog/manager.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/shared/blog/manager.py	Fri Mar 16 08:17:54 2018 +0100
@@ -19,6 +19,7 @@
 from pyams_content.component.illustration import IIllustrationTarget
 from pyams_content.component.paragraph.interfaces import IParagraphFactorySettings
 from pyams_content.component.theme.interfaces import IThemesManagerTarget
+from pyams_content.features.preview.interfaces import IPreviewTarget
 from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget
 from pyams_content.shared.blog.interfaces import IBlogManager, BLOG_CONTENT_TYPE, IBlogFolder
 from pyams_portal.interfaces import IPortalContext
@@ -49,7 +50,7 @@
 
 
 @implementer(IBlogManager, IParagraphFactorySettings, IThemesManagerTarget, IPictogramManagerTarget,
-             IIllustrationTarget, IPortalContext, IAttributeAnnotatable)
+             IIllustrationTarget, IPortalContext, IPreviewTarget, IAttributeAnnotatable)
 class BlogManager(SharedTool, UserSkinnableContent):
     """Nlog manager class"""
 
--- a/src/pyams_content/shared/form/zmi/preview.py	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-#
-# Copyright (c) 2008-2015 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.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard library
-
-# import interfaces
-from pyams_content.features.renderer.interfaces import IContentRenderer
-from pyams_content.shared.form.interfaces import IFormFieldContainerTarget, IFormFieldContainer
-from pyams_form.interfaces.form import IFormHelp
-from pyams_i18n.interfaces import II18n
-from pyams_skin.layer import IPyAMSLayer
-
-# import packages
-from pyams_content.features.renderer.zmi import BaseContentRenderer
-from pyams_form.form import InnerAddForm
-from pyams_form.help import FormHelp
-from pyams_utils.adapter import adapter_config
-from z3c.form import field, button
-from zope.interface import Interface
-
-
-class FormFieldContainerPreviewDisplayForm(InnerAddForm):
-    """Form fields container preview display form"""
-
-    @property
-    def legend(self):
-        return II18n(self.context).query_attribute('user_title', request=self.request)
-
-    @property
-    def fields(self):
-        fields = field.Fields(*IFormFieldContainer(self.context).get_fields())
-        if self.context.use_captcha:
-            # TODO: add captcha
-            # fields += field.Fields(Captcha(title='', description='', required=True))
-            pass
-        return fields
-
-    buttons = button.Buttons(Interface)
-
-    def updateWidgets(self, prefix=None):
-        super(FormFieldContainerPreviewDisplayForm, self).updateWidgets(prefix)
-        for widget in self.widgets.values():
-            field = IFormFieldContainer(self.context).get(widget.field.__name__)
-            if field is not None:
-                widget.placeholder = field.placeholder
-                if field.field_type == 'text':
-                    widget.widget_css_class = 'textarea'
-
-
-@adapter_config(context=(IFormFieldContainerTarget, IPyAMSLayer, FormFieldContainerPreviewDisplayForm),
-                provides=IFormHelp)
-class FormFieldContainerPreviewHelp(FormHelp):
-    """Form field container preview help adapter"""
-
-    def __new__(cls, context, request, view):
-        if not context.header:
-            return None
-        return FormHelp.__new__(cls)
-
-    @property
-    def message(self):
-        return II18n(self.context).query_attribute('header', request=self.request)
-
-    message_format = 'text'
-
-
-@adapter_config(name='form-preview', context=(IFormFieldContainerTarget, IPyAMSLayer),
-                provides=IContentRenderer)
-class FormFieldContainerPreview(BaseContentRenderer):
-    """Form field container preview"""
-
-    weight = 20
-    display_form = None
-
-    def __init__(self, context, request):
-        super(FormFieldContainerPreview, self).__init__(context, request)
-        self.display_form = FormFieldContainerPreviewDisplayForm(context, self.request)
-
-    def update(self):
-        super(FormFieldContainerPreview, self).update()
-        self.display_form.update()
-
-    def render(self):
-        return self.display_form.render()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/form/zmi/render.py	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,96 @@
+#
+# Copyright (c) 2008-2015 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.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_content.shared.form.interfaces import IFormFieldContainerTarget, IFormFieldContainer
+from pyams_form.interfaces.form import IFormHelp
+from pyams_i18n.interfaces import II18n
+from pyams_skin.layer import IPyAMSLayer
+
+# import packages
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_form.form import InnerAddForm
+from pyams_form.help import FormHelp
+from pyams_utils.adapter import adapter_config
+from z3c.form import field, button
+from zope.interface import Interface
+
+
+class FormFieldContainerDisplayForm(InnerAddForm):
+    """Form fields container display form"""
+
+    @property
+    def legend(self):
+        return II18n(self.context).query_attribute('user_title', request=self.request)
+
+    @property
+    def fields(self):
+        fields = field.Fields(*IFormFieldContainer(self.context).get_fields())
+        if self.context.use_captcha:
+            # TODO: add captcha
+            # fields += field.Fields(Captcha(title='', description='', required=True))
+            pass
+        return fields
+
+    buttons = button.Buttons(Interface)
+
+    def updateWidgets(self, prefix=None):
+        super(FormFieldContainerDisplayForm, self).updateWidgets(prefix)
+        for widget in self.widgets.values():
+            field = IFormFieldContainer(self.context).get(widget.field.__name__)
+            if field is not None:
+                widget.placeholder = field.placeholder
+                if field.field_type == 'text':
+                    widget.widget_css_class = 'textarea'
+
+
+@adapter_config(context=(IFormFieldContainerTarget, IPyAMSLayer, FormFieldContainerDisplayForm),
+                provides=IFormHelp)
+class FormFieldContainerDisplayFormHelp(FormHelp):
+    """Form field container display form help adapter"""
+
+    def __new__(cls, context, request, view):
+        if not context.header:
+            return None
+        return FormHelp.__new__(cls)
+
+    @property
+    def message(self):
+        return II18n(self.context).query_attribute('header', request=self.request)
+
+    message_format = 'text'
+
+
+@adapter_config(name='form-render', context=(IFormFieldContainerTarget, IPyAMSLayer),
+                provides=IContentRenderer)
+class FormFieldContainerRenderer(BaseContentRenderer):
+    """Form field container renderer"""
+
+    weight = 20
+    display_form = None
+
+    def __init__(self, context, request):
+        super(FormFieldContainerRenderer, self).__init__(context, request)
+        self.display_form = FormFieldContainerDisplayForm(context, self.request)
+
+    def update(self):
+        super(FormFieldContainerRenderer, self).update()
+        self.display_form.update()
+
+    def render(self):
+        return self.display_form.render()
--- a/src/pyams_content/shared/imagemap/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/shared/imagemap/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -18,7 +18,7 @@
 # import interfaces
 from pyams_content.component.association.interfaces import IAssociationInfo
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor, IParagraphContainerView
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
 from pyams_content.shared.common.interfaces import IWfSharedContent
@@ -154,13 +154,13 @@
 
 
 #
-# Image map paragraph preview
+# Image map paragraph renderer
 #
 
-@adapter_config(context=(IImageMapParagraph, IPyAMSLayer), provides=IParagraphPreview)
-@template_config(template='templates/paragraph-preview.pt', layer=IPyAMSLayer)
-class ImagemapParagraphPreview(BaseContentProvider):
-    """Image map paragraph preview"""
+@adapter_config(context=(IImageMapParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+@template_config(template='templates/paragraph-render.pt', layer=IPyAMSLayer)
+class ImagemapParagraphRenderer(BaseContentProvider):
+    """Image map paragraph renderer"""
 
     language = None
 
--- a/src/pyams_content/shared/imagemap/zmi/preview.py	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#
-# Copyright (c) 2008-2015 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.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard library
-
-# import interfaces
-from pyams_content.component.association.interfaces import IAssociationInfo
-from pyams_content.features.preview.zmi.interfaces import IPreviewForm
-from pyams_content.shared.imagemap.interfaces import IWfImageMap
-from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager
-from pyams_skin.layer import IPyAMSLayer
-from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
-
-# import packages
-from pyams_template.template import template_config
-from pyams_viewlet.viewlet import viewlet_config
-
-
-@viewlet_config(name='imagemap-preview', context=IWfImageMap, layer=IPyAMSLayer,
-                view=IPreviewForm, manager=IWidgetsSuffixViewletsManager,
-                permission=VIEW_SYSTEM_PERMISSION, weight=100)
-@template_config(template='templates/preview.pt', layer=IPyAMSLayer)
-class ImagemapPreview(object):
-    """Image map preview"""
-
-    def get_item_info(self, item):
-        return IAssociationInfo(item, None)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/imagemap/zmi/render.py	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2008-2015 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.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.component.association.interfaces import IAssociationInfo
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_content.shared.imagemap.interfaces import IWfImageMap
+from pyams_skin.layer import IPyAMSLayer
+
+# import packages
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+
+
+@adapter_config(name='imagemap-render', context=(IWfImageMap, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/render.pt', layer=IPyAMSLayer)
+class ImagemapRenderer(BaseContentRenderer):
+    """Image map renderer"""
+
+    weight = 20
+
+    def get_item_info(self, item):
+        return IAssociationInfo(item, None)
--- a/src/pyams_content/shared/imagemap/zmi/templates/paragraph-preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-<h3 tal:content="view.title">title</h3>
-<div class="no-padding" i18n:domain="pyams_content"
-	 data-ams-plugins="pyams_content"
-	 tal:define="imagemap context.get_target()"
-	 tal:attributes="data-ams-plugin-pyams_content-src extension:resource_path('pyams_content.skin:pyams_content')">
-	<img usemap="#imagemap_preview"
-		 tal:define="image i18n:imagemap.image"
-		 tal:attributes="src extension:absolute_url(image);
-						 usemap string:#imagemap_preview_${context.__name__}"
-		 data-ams-callback="PyAMS_content.imgmap.initPreview" />
-	<map name="imagemap_preview"
-		 tal:attributes="name string:imagemap_preview_${context.__name__}">
-		<tal:loop repeat="area imagemap.areas.values()">
-			<tal:var define="item imagemap.get_association(area)"
-					 condition="item and item.visible">
-				<area shape="poly"
-					  tal:define="info view.get_item_info(item);
-								  area_title i18n:area.title;
-								  item_title i18n:info.user_title;
-								  title area_title or item_title;"
-					  tal:attributes="coords area.area;
-									  href item.get_url(request);
-									  title title;" />
-			</tal:var>
-		</tal:loop>
-	</map>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/imagemap/zmi/templates/paragraph-render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,27 @@
+<h3 tal:content="view.title">title</h3>
+<div class="no-padding" i18n:domain="pyams_content"
+	 data-ams-plugins="pyams_content"
+	 tal:define="imagemap context.get_target()"
+	 tal:attributes="data-ams-plugin-pyams_content-src extension:resource_path('pyams_content.skin:pyams_content')">
+	<img usemap="#imagemap_preview"
+		 tal:define="image i18n:imagemap.image"
+		 tal:attributes="src extension:absolute_url(image);
+						 usemap string:#imagemap_preview_${context.__name__}"
+		 data-ams-callback="PyAMS_content.imgmap.initPreview" />
+	<map name="imagemap_preview"
+		 tal:attributes="name string:imagemap_preview_${context.__name__}">
+		<tal:loop repeat="area imagemap.areas.values()">
+			<tal:var define="item imagemap.get_association(area)"
+					 condition="item and item.visible">
+				<area shape="poly"
+					  tal:define="info view.get_item_info(item);
+								  area_title i18n:area.title;
+								  item_title i18n:info.user_title;
+								  title area_title or item_title;"
+					  tal:attributes="coords area.area;
+									  href item.get_url(request);
+									  title title;" />
+			</tal:var>
+		</tal:loop>
+	</map>
+</div>
--- a/src/pyams_content/shared/imagemap/zmi/templates/preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-<div class="padding-y-5" i18n:domain="pyams_content"
-	 data-ams-plugins="pyams_content"
-	 tal:attributes="data-ams-plugin-pyams_content-src extension:resource_path('pyams_content.skin:pyams_content')">
-	<img usemap="#imagemap_preview"
-		 tal:define="image i18n:context.image"
-		 tal:attributes="src extension:absolute_url(image);"
-		 data-ams-callback="PyAMS_content.imgmap.initSummary" />
-	<map name="imagemap_preview">
-		<tal:loop repeat="area context.areas.values()">
-			<tal:var define="item context.get_association(area)"
-					 condition="item and item.visible">
-				<area shape="poly"
-					  tal:define="info view.get_item_info(item);
-								  area_title i18n:area.title;
-								  item_title i18n:info.user_title;
-								  title area_title or item_title;"
-					  tal:attributes="coords area.area;
-									  href item.get_url(request);
-									  title title;" />
-			</tal:var>
-		</tal:loop>
-	</map>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/imagemap/zmi/templates/render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,23 @@
+<div class="padding-y-5" i18n:domain="pyams_content"
+	 data-ams-plugins="pyams_content"
+	 tal:attributes="data-ams-plugin-pyams_content-src extension:resource_path('pyams_content.skin:pyams_content')">
+	<img usemap="#imagemap_preview"
+		 tal:define="image i18n:context.image"
+		 tal:attributes="src extension:absolute_url(image);"
+		 data-ams-callback="PyAMS_content.imgmap.initSummary" />
+	<map name="imagemap_preview">
+		<tal:loop repeat="area context.areas.values()">
+			<tal:var define="item context.get_association(area)"
+					 condition="item and item.visible">
+				<area shape="poly"
+					  tal:define="info view.get_item_info(item);
+								  area_title i18n:area.title;
+								  item_title i18n:info.user_title;
+								  title area_title or item_title;"
+					  tal:attributes="coords area.area;
+									  href item.get_url(request);
+									  title title;" />
+			</tal:var>
+		</tal:loop>
+	</map>
+</div>
--- a/src/pyams_content/shared/logo/zmi/paragraph.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/shared/logo/zmi/paragraph.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,7 +17,7 @@
 
 # import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainerTarget, IParagraphContainer, \
-    IParagraphPreview
+    IParagraphRenderer
 from pyams_content.component.paragraph.zmi.interfaces import IParagraphInnerEditor
 from pyams_content.interfaces import MANAGE_CONTENT_PERMISSION
 from pyams_content.shared.common import IWfSharedContent
@@ -31,7 +31,7 @@
 # import packages
 from pyams_content.component.paragraph.zmi import IParagraphContainerView, BaseParagraphAddMenu, \
     BaseParagraphAJAXAddForm, BaseParagraphPropertiesEditForm, BaseParagraphAJAXEditForm
-from pyams_content.features.renderer.zmi import BaseRenderedContentPreview
+from pyams_content.features.renderer.zmi import BaseRenderedContentRenderer
 from pyams_content.features.renderer.zmi.widget import RendererFieldWidget
 from pyams_content.shared.logo.paragraph import LogosParagraph
 from pyams_pagelet.pagelet import pagelet_config
@@ -150,9 +150,9 @@
 
 
 #
-# Logos paragraph preview
+# Logos paragraph renderer
 #
 
-@adapter_config(context=(ILogosParagraph, IPyAMSLayer), provides=IParagraphPreview)
-class LogosParagraphPreview(BaseRenderedContentPreview):
-    """Logos paragraph preview"""
+@adapter_config(context=(ILogosParagraph, IPyAMSLayer), provides=IParagraphRenderer)
+class LogosParagraphRenderer(BaseRenderedContentRenderer):
+    """Logos paragraph renderer"""
--- a/src/pyams_content/shared/site/folder.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/shared/site/folder.py	Fri Mar 16 08:17:54 2018 +0100
@@ -17,6 +17,7 @@
 
 # import interfaces
 from pyams_content.component.illustration import IIllustrationTarget
+from pyams_content.features.preview.interfaces import IPreviewTarget
 from pyams_content.interfaces import MANAGE_SITE_PERMISSION
 from pyams_content.shared.site.interfaces import ISiteFolder, ISiteManager, ISiteFolderRoles
 from pyams_form.interfaces.form import IFormContextPermissionChecker
@@ -42,7 +43,7 @@
 
 
 @implementer(IDefaultProtectionPolicy, ISiteFolder, ISiteFolderRoles,
-             IIllustrationTarget, IPortalContext, IAttributeAnnotatable)
+             IIllustrationTarget, IPortalContext, IPreviewTarget, IAttributeAnnotatable)
 class SiteFolder(SiteContainerMixin, OrderedContainer, BaseSharedTool):
     """Site folder persistent class"""
 
--- a/src/pyams_content/shared/site/manager.py	Thu Mar 15 12:06:23 2018 +0100
+++ b/src/pyams_content/shared/site/manager.py	Fri Mar 16 08:17:54 2018 +0100
@@ -19,6 +19,7 @@
 from pyams_content.component.illustration import IIllustrationTarget
 from pyams_content.component.paragraph.interfaces import IParagraphFactorySettings
 from pyams_content.component.theme.interfaces import IThemesManagerTarget
+from pyams_content.features.preview.interfaces import IPreviewTarget
 from pyams_content.interfaces import MANAGE_SITE_PERMISSION
 from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget
 from pyams_content.shared.site.interfaces import ISiteManager, TOPIC_CONTENT_TYPE
@@ -48,7 +49,7 @@
 
 
 @implementer(ISiteManager, IParagraphFactorySettings, IThemesManagerTarget, IPictogramManagerTarget,
-             IIllustrationTarget, IPortalContext, IAttributeAnnotatable)
+             IIllustrationTarget, IPortalContext, IPreviewTarget, IAttributeAnnotatable)
 class SiteManager(SiteContainerMixin, OrderedContainer, BaseSharedTool, UserSkinnableContent):
     """Site manager persistent class"""
 
--- a/src/pyams_content/shared/view/zmi/preview.py	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-#
-# Copyright (c) 2008-2015 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.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard library
-
-# import interfaces
-from pyams_content.features.preview.zmi.interfaces import IPreviewForm
-from pyams_content.shared.view.interfaces import IWfView
-from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager
-from pyams_skin.layer import IPyAMSLayer
-from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
-
-# import packages
-from pyams_template.template import template_config
-from pyams_viewlet.viewlet import viewlet_config
-
-
-@viewlet_config(name='view-preview', context=IWfView, layer=IPyAMSLayer,
-                view=IPreviewForm, manager=IWidgetsSuffixViewletsManager,
-                permission=VIEW_SYSTEM_PERMISSION, weight=100)
-@template_config(template='templates/preview.pt', layer=IPyAMSLayer)
-class SharedViewPreview(object):
-    """Shared view preview"""
-
-    @property
-    def items(self):
-        return self.context.get_results(self.context)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/view/zmi/render.py	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2008-2015 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.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_content.shared.view.interfaces import IWfView
+from pyams_skin.layer import IPyAMSLayer
+
+# import packages
+from pyams_content.features.renderer.zmi import BaseContentRenderer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+
+
+@adapter_config(name='view-render', context=(IWfView, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/render.pt', layer=IPyAMSLayer)
+class ViewRenderer(BaseContentRenderer):
+    """Shared view renderer"""
+
+    weight = 20
+
+    @property
+    def items(self):
+        return self.context.get_results(self.context)
--- a/src/pyams_content/shared/view/zmi/templates/preview.pt	Thu Mar 15 12:06:23 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<fieldset i18n:domain="pyams_content">
-	<legend class="inner" i18n:translate="">View result items</legend>
-	<div class="alert alert-info padding-5" i18n:translate="">
-		WARNING: items displayed in this preview are out of context!!
-	</div>
-	<tal:loop repeat="item view.items">
-		<span tal:content="i18n:item.title" /><br />
-	</tal:loop>
-</fieldset>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/view/zmi/templates/render.pt	Fri Mar 16 08:17:54 2018 +0100
@@ -0,0 +1,9 @@
+<fieldset i18n:domain="pyams_content">
+	<legend class="inner" i18n:translate="">View result items</legend>
+	<div class="alert alert-info padding-5" i18n:translate="">
+		WARNING: items displayed in this preview are out of context!!
+	</div>
+	<tal:loop repeat="item view.items">
+		<span tal:content="i18n:item.title" /><br />
+	</tal:loop>
+</fieldset>