--- a/src/source/appextend.rst Wed May 16 12:00:26 2018 +0200
+++ b/src/source/appextend.rst Wed May 16 14:06:43 2018 +0200
@@ -5,59 +5,51 @@
**Portlets** are pluggable user interface software components that are managed and displayed in a web portal,
for example an enterprise portal or a web CMS. A portlet can aggregate (integrate) and personalize content from
-different sources within a web page. A portlet responds to requests from a web client with and generates dynamic content.
-(*reference:* `Wiki portlet`_)
+different sources within a web page. A portlet responds to requests from a web client and generates dynamic content
+(*reference:* `Wiki portlet`_).
.. _`wiki portlet`: https://en.wikipedia.org/wiki/Portlet
-**Pyams Portal** provides predefined portlets that to compose and organize the structure of a website.
+**PyAMS Portal** provides the portal engine but only a very small set of predefined portlets that can be used to compose
+and organize the structure of a web page; additional portlets are provided by other packages, like
+:ref:`pyams_content`.
+
-1. Define a Portlet setting
-'''''''''''''''''''''''''''
+1. Define portlet settings
+''''''''''''''''''''''''''
-Portlet setting interface are defined in ``interfaces.py``, you can use IPortletSettings or extend the interface
-by adding an additional properties for example:
+Portlet settings interface are defined in ``interfaces.py``, you can use :py:class:`pyams_portal.interfaces.IPortletSettings`
+or extend the interface by adding additional properties for example:
.. code-block:: python
from zope.schema import Text
+ NEW_PORTLET_NAME = 'new.portlet'
+
class INewPortletSettings(IPortletSettings):
comment = Text(title=_("Comment"),
- required=True,
- default=True)
+ required=True)
-PortletSetting component does what IPortletSettings describes. This is usually referred to as the implementation
-of IPortletSettings.
+
+A :py:class:`pyams_portal.portlet.PortletSettings` persistent subclass then implements what IPortletSettings describes:
.. code-block:: python
- @implementer(IPortletSettings)
- class ImagePortletSettings(PortletSettings):
- """Image portlet settings"""
-
- _image = FileProperty(IImagePortletSettings['image'])
+ @implementer(INewPortletSettings)
+ class NewPortletSettings(PortletSettings):
+ """Portlet settings"""
- @property
- def image(self):
- return self._image
-
- @image.setter
- def image(self, value):
- self._image = value
- if (value is not None) and (value is not DELETED_FILE):
- alsoProvides(self._image, IResponsiveImage)
-
+ comment = FieldProperty(INewPortletSettings['comment'])
2. Create Portlet
'''''''''''''''''
-The Porltet component is a utility, it implement the IPortlet interface and it registered by the portlet_config adapter
-
-To register a new portlet you must specify the settings_class associated
+The Portlet component is a utility, which implements the :py:class:`pyams_portal.interfaces.IPortlet` interface and is
+registered by the :py:func:`pyams_portal.portlet.portlet_config` decorator;
.. code-block:: python
@@ -65,51 +57,111 @@
class ImagePortlet(Portlet):
"""Image portlet"""
- name = IMAGE_PORTLET_NAME
- label = _("Image")
+ name = NEW_PORTLET_NAME
+ label = _("New portlet")
toolbar_image = None
toolbar_css_class = 'fa fa-fw fa-2x fa-picture-o'
- settings_class = ImagePortletSettings
+ settings_class = NewPortletSettings
-
-4. Create HTML template
-'''''''''''''''''''''''
+Where:
+ - **permission**: permission required to display this portlet content
+ - **name**: internal name given to this portlet. This name must be unique between all portlets, so using your own
+ namespace into this name is generally a good option!
+ - **label**: user label given to this portlet
+ - **toolbar_image**: URL of an image used to display portlet button into ZMI toolbar, if any
+ - **toolbar_css_class**: CSS class used to display portlet button into ZMI toolbar, if any
+ - **settings_class**: class used to store portlet settings.
-.. code-block:: genshi
+3. Create portlet settings edit form
+''''''''''''''''''''''''''''''''''''
+
+Portlet settings have to be updated through management interface via a :py:class:`pyams_portal.zmi.portlet.PortletSettingsEditor`
+subform:
- <span>${view.settings.comment}</span>
+.. code-block:: python
+
+ @pagelet_config(name='properties.html', context=INewPortletSettings, layer=IPyAMSLayer,
+ permission=VIEW_SYSTEM_PERMISSION)
+ class NewPortletSettingsEditor(PortletSettingsEditor):
+ """New portlet settings editor"""
+
+ settings = INewPortletSettings
+ @adapter_config(name='properties.json', context=(INewPortletSettings, IPyAMSLayer), provides=IPagelet)
+ class NewPortletSettingsAJAXEditor(AJAXEditForm, NewPortletSettingsEditor):
+ """New portlet settings editor, JSON renderer"""
-5. Renderer
-'''''''''''
+
+4. Previewing portlet content
+'''''''''''''''''''''''''''''
+
+A *previewer* is used into ZMI to display portlet content into portal template definition page:
.. code-block:: python
- @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IImagePortletSettings), provides=IPortletRenderer)
- @template_config(template='image.pt', layer=IPyAMSLayer)
- class ImagePortletRenderer(PortletRenderer):
- """Image portlet renderer"""
-
- label = _("Responsive image renderer")
+ @adapter_config(context=(Interface, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletPreviewer)
+ @template_config(template='my-portlet-preview.pt', layer=IPyAMSLayer)
+ class NewPortletPreviewer(PortletPreviewer):
+ """New portlet previewer"""
+The previewer template is a Chameleon template:
-6. Zmi integration module
-'''''''''''''''''''''''''
+.. code-block:: genshi
+
+ <tal:var define="settings view.settings">
+ <tal:if condition="settings.visible">
+ <div tal:content="settings.comment">Comment</div>
+ </tal:if>
+ <tal:if condition="not settings.visible">
+ <div class="text-center padding-y-5">
+ <span class="fa-stack fa-lg">
+ <i class="fa fa-eye fa-stack-1x"></i>
+ <i class="fa fa-ban fa-stack-2x text-danger"></i>
+ </span>
+ </div>
+ </tal:if>
+ </tal:var>
+
+Here we check if portlet is visible or not to display a small icon when hidden; otherwise we display entered comment.
+
+
+5. Rendering portlet content
+''''''''''''''''''''''''''''
+
+A *renderer* is used to display portlet content into rendered page content:
.. code-block:: python
- @pagelet_config(name='properties.html', context=IImagePortletSettings, request_type=IPyAMSLayer,
- permission=VIEW_SYSTEM_PERMISSION)
- class ImagePortletSettingsEditor(PortletSettingsEditor):
- """Image portlet settings editor"""
+ @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletRenderer)
+ @template_config(template='my-portlet-render.pt', layer=IPyAMSLayer)
+ class NewPortletRenderer(PortletRenderer):
+ """New portlet renderer"""
- settings = IImagePortletSettings
+ label = _("Default comment renderer")
+Each renderer template is also a Chameleon template:
+.. code-block:: genshi
+
+ <div class="comment" tal:content="view.settings.comment">Comment</div>
+
+
+This is the configuration of a *default* renderer defined for this portlet; you can provide several renderers for a
+given portlet by given distinct names to the adapters:
+
+.. code-block:: python
+
+ @adapter_config(name='another-renderer',
+ context=(IPortalContext, IPyAMSLayer, Interface, INewPortletSettings), provides=IPortletRenderer)
+ @template_config(template='my-portlet-render-2.pt', layer=IPyAMSLayer)
+ class AnotherNewPortletRenderer(PortletRenderer):
+ """Another new portlet renderer"""
+
+ label = _("Another comment renderer")