diff -r cfb7276fdd33 -r dc2bd8068d7a src/source/appextend.rst --- 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: - ${view.settings.comment} +.. 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 + + + +
Comment
+
+ +
+ + + + +
+
+
+ +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 + +
Comment
+ + +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")