Updated doc doc-dc
authorDamien Correia
Mon, 17 Dec 2018 17:19:35 +0100
branchdoc-dc
changeset 122 7e69ecc9fd43
parent 121 98a84761634f
child 124 696f58cb5bdd
Updated doc
src/source/dev_guide/adv-features.rst
src/source/dev_guide/dev-form.rst
src/source/dev_guide/howto-form.rst
src/source/dev_guide/howto-paragraph.rst
src/source/dev_guide/howto-portlet.rst
src/source/dev_guide/howto-rename.rst
src/source/dev_guide/new-form.rst
src/source/index.rst
--- a/src/source/dev_guide/adv-features.rst	Fri Dec 14 12:16:12 2018 +0100
+++ b/src/source/dev_guide/adv-features.rst	Mon Dec 17 17:19:35 2018 +0100
@@ -11,6 +11,68 @@
 Renaming persistent classes
 ---------------------------
 
+PyAMS provides `zodbupdate` script to update easily update the change in ZODB. Because, when you develop new features
+to PyAMS we sometimes have to rename or modify classes of already stored objects and if you do that you will never access
+yours objects.
+
+To rename classes of existing objects:
+
+**1) Include you package in the require resource for you webapp**
+
+
+.. code-block:: python
+
+    requires = [
+        'mypackage',
+        ...
+    ]
+
+**2) Add the Entry points**
+
+
+In the `setup.py` file add 'zodbupdate' params into entry_points where is store zodbupdate directives
+
+.. code-block:: python
+
+      entry_points={
+          'zodbupdate': [
+              'renames = mypackage.generations:RENAMED_CLASSES'
+          ]
+      }
+
+
+
+**3) Create a module named** ``generation`` **with the migration directives**
+
+
+.. code-block:: python
+
+    RENAMED_CLASSES = {
+        'mypackage.mymodule MyOldClass': 'mypackage.mymodule MyNewClass'
+    }
+
+
+**4) Run the commands** ``buildout`` .
+
+.. code-block:: console
+
+    $ mypackage/bin/buildout
+    $ webapp/bin/buildout
+
+
+The ``buildout`` command going to install correctly the package and add the new entry_points references in entry_points.txt
+
+**5)  Run the commands** ``zodbupdate``
+
+To finish run `zodbupdate` to apply the changes describe in `RENAMED_CLASSES`
+
+.. code-block:: console
+
+    $   bin/zodbupdate --config etc/zodbupdate-zeo.conf
+
+
+Where `zodbupdate-zeo.conf` is the configuration file to access to the ZODB.
+
 Including SQLAlchemy
 --------------------
 
--- a/src/source/dev_guide/dev-form.rst	Fri Dec 14 12:16:12 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-.. _devform:
-
-Understanding PyAMS form
-========================
--- a/src/source/dev_guide/howto-form.rst	Fri Dec 14 12:16:12 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-.. _formhowto:
-
-
-How to create a form to a component
-===================================
-
-
-When creating a new object to the zodb, the construction of the form can't be based on an object passed context.
-To build the form we use a default factory that is attached to the container of the element.
-
-
-1) Container factory
---------------------
-
-Declaration of the **factory** of `ContactPhoneParagraph`
-
-.. code-block:: python
-
-    @utility_config(name=CONTACT_PHONE_PARAGRAPH_TYPE, provides=IParagraphFactory)
-    class ContactPhoneParagraphFactory(BaseParagraphFactory):
-        """Contact paragraph factory"""
-
-        name = _("Contact Phone card")
-        content_type = ContactPhoneParagraph
-        secondary_menu = True
-
-
-
-For example :py:class:`IParagraphContainerTarget`, it's a marker interface for paragraph containers.
-We could use this interface as context to declare a new pagelet.
-
-
-.. code-block:: python
-
-    from pyams_form.form import ajax_config
-
-
-    @pagelet_config(name='add-contact-phone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
-                    permission=MANAGE_CONTENT_PERMISSION)
-    @ajax_config(name='add-contact-phone-paragraph.json', context=IParagraphContainerTarget, layer=IPyAMSLayer,
-                 base=BaseParagraphAJAXAddForm)
-    class ContactPhoneParagraphAddForm(AdminDialogAddForm):
-        """Contact paragraph add form"""
-
-        legend = _("Add new phone contact card")
-        dialog_class = 'modal-large'
-        icon_css_class = 'fa fa-fw fa-phone'
-        edit_permission = MANAGE_CONTENT_PERMISSION
-
-        #Retrieve fields from the interface of the component
-        fields = field.Fields(IContactPhoneParagraph).omit('__parent__', '__name__', 'visible')
-
-
-        def create(self, data):
-            """Create one instance of the component"""
-            return ContactPhoneParagraph()
-
-        def add(self, object):
-            """Add the new component to the container that implement the interface `IParagraphContainer` """
-            IParagraphContainer(self.context).append(object)
-
-The associate form field are generated automatically based on this interface attributes
-
-:py:function:`@ajax_config()` allows the form is working with ajax requests by providing `json` content.
-
-
-
-2) Edit form
-------------
-
-.. code-block:: python
-
-    @adapter_config(context=(IContactPhoneParagraph, IPyAMSLayer), provides=IParagraphInnerEditor)
-                permission=MANAGE_CONTENT_PERMISSION)
-    @ajax_config(name='inner-properties.json', context=IContactPhoneParagraph, layer=IPyAMSLayer,
-             base=BaseParagraphAJAXEditForm)
-    @implementer(IInnerForm)
-    class ContactPhoneParagraphInnerEditForm(ContactPhoneParagraphPropertiesEditForm):
-        """Contact paragraph inner edit form"""
-
-        legend = None
-
-        @property
-        def buttons(self):
-            if self.mode == INPUT_MODE:
-                return button.Buttons(IParagraphEditFormButtons)
-            else:
-                return button.Buttons()
-
-        def get_ajax_output(self, changes):
-            output = super(ContactParagraphInnerAJAXEditForm, self).get_ajax_output(changes)
-            updated = changes.get(IBaseParagraph, ())
-            if 'title' in updated:
-                output.setdefault('events', []).append(get_json_paragraph_refresh_event(self.context, self.request))
-            updated = changes.get(IContactParagraph, ())
-            if ('photo' in updated) or ('renderer' in updated):
-                # we have to commit transaction to be able to handle blobs...
-                if 'photo' in updated:
-                    ITransactionManager(self.context).get().commit()
-                output.setdefault('events', []).append(get_json_form_refresh_event(self.context, self.request,
-                                                                                   ContactParagraphInnerEditForm))
-            return output
-
--- a/src/source/dev_guide/howto-paragraph.rst	Fri Dec 14 12:16:12 2018 +0100
+++ b/src/source/dev_guide/howto-paragraph.rst	Mon Dec 17 17:19:35 2018 +0100
@@ -100,31 +100,16 @@
 Paragraph in the ZMI
 """"""""""""""""""""
 
-
-To display and manage the new paragraph in the ZMI, you should create this associated forms
+1) Container Paragraph
+----------------------
 
-1) Paragraph factory
---------------------
+For example :py:class:`IParagraphContainerTarget`, it's a marker interface for paragraph containers.
 
 To create a new element instance inside the zodb, we need a container to this object. PyAMS provide
-`IParagraphContainerTarget`, it's the default container for all paragraphs. We could use this container interface
-as context to create a new paragraph.
-
-
-Declaration of the **factory** of `ContactPhoneParagraph`
-
-.. code-block:: python
+`IParagraphContainerTarget`, it's the default marker interface container for all paragraphs.
+We could use this interface as context to declare a new pagelet.
 
-    @utility_config(name=CONTACT_PHONE_PARAGRAPH_TYPE, provides=IParagraphFactory)
-    class ContactPhoneParagraphFactory(BaseParagraphFactory):
-        """Contact paragraph factory"""
-
-        name = _("Contact Phone card")
-        content_type = ContactPhoneParagraph
-        secondary_menu = True
-
-
-Definition of a form to create a new ContactPhone instance
+Definition of a Contact Phone form to create a new ContactPhone object
 
 .. code-block:: python
 
@@ -152,6 +137,8 @@
             IParagraphContainer(self.context).append(object)
 
 
+To display and manage the new paragraph in the ZMI, you should create this associated forms
+
 2) Create the Paragraph addform button in the menu
 --------------------------------------------------
 
@@ -209,7 +196,7 @@
 
 
 4) Create an Edit modal form
------------------------------
+----------------------------
 
 This form is used inside modals popup
 
@@ -241,6 +228,27 @@
     .. image:: ../_static/select_paragraph.png
 
 
+5) Paragraph Factory
+--------------------
+
+If you want to create automatically a paragraph object for a shared content you must define a factory
+
+Declaration of the **factory** of `ContactPhoneParagraph`
+
+.. code-block:: python
+
+    @utility_config(name=CONTACT_PHONE_PARAGRAPH_TYPE, provides=IParagraphFactory)
+    class ContactPhoneParagraphFactory(BaseParagraphFactory):
+        """Contact paragraph factory"""
+
+        name = _("Contact Phone card")
+        content_type = ContactPhoneParagraph
+        secondary_menu = True
+
+When the contributors will create new shared content with predefined paragraphs,
+it's the container factory class that will be used to create the paragraph object.
+
+
 How to associate links or Illustrations to a Paragraph ?
 ========================================================
 
--- a/src/source/dev_guide/howto-portlet.rst	Fri Dec 14 12:16:12 2018 +0100
+++ b/src/source/dev_guide/howto-portlet.rst	Mon Dec 17 17:19:35 2018 +0100
@@ -17,12 +17,45 @@
 :ref:`pyams_content`.
 
 
-1. Define portlet settings
-''''''''''''''''''''''''''
+Create Portlet
+---------------
+
+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
+
+    @portlet_config(permission=VIEW_PERMISSION)
+    class ImagePortlet(Portlet):
+        """Image portlet"""
+
+        name = NEW_PORTLET_NAME
+        label = _("New portlet")
+
+        toolbar_image = None
+        toolbar_css_class = 'fa fa-fw fa-2x fa-picture-o'
+
+
+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
+
+NB: the argument **settings_class** could be set to add a portlet settings (see below).
+
+
+Portlet settings
+----------------
 
 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:
 
+1) create portlet settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 .. code-block:: python
 
     from zope.schema import Text
@@ -46,11 +79,10 @@
         comment = FieldProperty(INewPortletSettings['comment'])
 
 
-2. Create Portlet
-'''''''''''''''''
+2. declare the settings portlet
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-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;
+Add the settings portlet class inside the portlet
 
 .. code-block:: python
 
@@ -63,24 +95,14 @@
 
         toolbar_image = None
         toolbar_css_class = 'fa fa-fw fa-2x fa-picture-o'
-
         settings_class = NewPortletSettings
 
 
-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.
 
+3. portlet settings edit form
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-3. Create portlet settings edit form
-''''''''''''''''''''''''''''''''''''
-
-Portlet settings have to be updated through management interface via a :py:class:`pyams_portal.zmi.portlet.PortletSettingsEditor`
+Portlet settings have to be updated through management interface (ZMI) via a :py:class:`pyams_portal.zmi.portlet.PortletSettingsEditor`
 subform:
 
 .. code-block:: python
@@ -98,8 +120,8 @@
         """New portlet settings editor, JSON renderer"""
 
 
-4. Previewing portlet content
-'''''''''''''''''''''''''''''
+Previewing portlet content
+--------------------------
 
 A *previewer* is used into ZMI to display portlet content into portal template definition page:
 
@@ -132,8 +154,8 @@
 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
-''''''''''''''''''''''''''''
+Rendering portlet content
+-------------------------
 
 A *renderer* is used to display portlet content into rendered page content:
 
--- a/src/source/dev_guide/howto-rename.rst	Fri Dec 14 12:16:12 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-.. _renamehowto:
-
-
-How to rename classes of existing objects ?
-===========================================
-
-
-PyAMS provides `zodbupdate` script to update easily update the change in ZODB. Because, when you develop new features
-to PyAMS we sometimes have to rename or modify classes of already stored objects and if you do that you will never access
-yours objects
-
-
-**1) Include you package in the require resource for you webapp**
-
-
-.. code-block:: python
-
-    requires = [
-        'mypackage',
-        ...
-    ]
-
-**2) Add the Entry points**
-
-
-In the `setup.py` file add 'zodbupdate' params into entry_points where is store zodbupdate directives
-
-.. code-block:: python
-
-      entry_points={
-          'zodbupdate': [
-              'renames = mypackage.generations:RENAMED_CLASSES'
-          ]
-      }
-
-
-
-**3) Create a module named** ``generation`` **with the migration directives**
-
-
-.. code-block:: python
-
-    RENAMED_CLASSES = {
-        'mypackage.mymodule MyOldClass': 'mypackage.mymodule MyNewClass'
-    }
-
-
-**4) Run the commands** ``buildout`` .
-
-.. code-block:: console
-
-    $ mypackage/bin/buildout
-    $ webapp/bin/buildout
-
-
-The ``buildout`` command going to install correctly the package and add the new entry_points references in entry_points.txt
-
-**5)  Run the commands** ``zodbupdate``
-
-To finish run `zodbupdate` to apply the changes describe in `RENAMED_CLASSES`
-
-.. code-block:: console
-
-    $   bin/zodbupdate --config etc/zodbupdate-zeo.conf
-
-
-Where `zodbupdate-zeo.conf` is the configuration file to access to the ZODB.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/source/dev_guide/new-form.rst	Mon Dec 17 17:19:35 2018 +0100
@@ -0,0 +1,129 @@
+.. _newform:
+
+Understanding PyAMS form
+========================
+
+
+The forms are based on ZC3.form framework. It provide HTML and Json
+
+
+.. seealso::
+
+	https://z3cform.readthedocs.io/en/latest/
+
+
+
+
+
+.. _formhowto:
+
+
+How to create a form to a component
+-----------------------------------
+
+
+The standard form creation with Z3C is described in the following link.
+
+	https://z3cform.readthedocs.io/en/latest/mustread/form.html
+
+
+PyAMS Form Integration
+----------------------
+
+
+When creating a new object to the zodb, the construction of the form can't be based on an object passed context.
+To build the form we use a default factory that is attached to the container of the element.
+
+
+1) Add Form
+^^^^^^^^^^^
+
+.. code-block:: python
+
+
+    @pagelet_config(name='add-contact-phone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
+                    permission=MANAGE_CONTENT_PERMISSION)
+    class ContactPhoneParagraphAddForm(AdminDialogAddForm):
+        """Contact paragraph add form"""
+
+        legend = _("Add new phone contact card")
+        dialog_class = 'modal-large'
+        icon_css_class = 'fa fa-fw fa-phone'
+        edit_permission = MANAGE_CONTENT_PERMISSION
+
+        #Retrieve fields from the interface of the component
+        fields = field.Fields(IContactPhoneParagraph).omit('__parent__', '__name__', 'visible')
+
+
+        def create(self, data):
+            """Create one instance of the component"""
+            return ContactPhoneParagraph()
+
+        def add(self, object):
+            """Add the new component to the container that implement the interface `IParagraphContainer` """
+            IParagraphContainer(self.context).append(object)
+
+The associate form field are generated automatically based on this interface attributes
+
+
+2) Ajax Form
+^^^^^^^^^^^^
+
+The decorator :py:function:`@ajax_config()` allows the form is working with ajax requests by providing `json` content.
+
+.. code-block:: python
+
+    from pyams_form.form import ajax_config
+
+
+    @pagelet_config(name='add-contact-phone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
+                    permission=MANAGE_CONTENT_PERMISSION)
+    @ajax_config(name='add-contact-phone-paragraph.json', context=IParagraphContainerTarget, layer=IPyAMSLayer,
+                 base=BaseParagraphAJAXAddForm)
+    class ContactPhoneParagraphAddForm(AdminDialogAddForm):
+        """Contact paragraph add form"""
+
+        legend = _("Add new phone contact card"
+		...
+
+
+
+3) Edit form
+^^^^^^^^^^^^
+
+.. code-block:: python
+
+    @adapter_config(context=(IContactPhoneParagraph, IPyAMSLayer), provides=IParagraphInnerEditor)
+                permission=MANAGE_CONTENT_PERMISSION)
+    @ajax_config(name='inner-properties.json', context=IContactPhoneParagraph, layer=IPyAMSLayer,
+             base=BaseParagraphAJAXEditForm)
+    @implementer(IInnerForm)
+    class ContactPhoneParagraphInnerEditForm(ContactPhoneParagraphPropertiesEditForm):
+        """Contact paragraph inner edit form"""
+
+        legend = None
+
+        @property
+        def buttons(self):
+            if self.mode == INPUT_MODE:
+                return button.Buttons(IParagraphEditFormButtons)
+            else:
+                return button.Buttons()
+
+        def get_ajax_output(self, changes):
+            output = super(ContactParagraphInnerAJAXEditForm, self).get_ajax_output(changes)
+            updated = changes.get(IBaseParagraph, ())
+            if 'title' in updated:
+                output.setdefault('events', []).append(get_json_paragraph_refresh_event(self.context, self.request))
+            updated = changes.get(IContactParagraph, ())
+            if ('photo' in updated) or ('renderer' in updated):
+                # we have to commit transaction to be able to handle blobs...
+                if 'photo' in updated:
+                    ITransactionManager(self.context).get().commit()
+                output.setdefault('events', []).append(get_json_form_refresh_event(self.context, self.request,
+                                                                                   ContactParagraphInnerEditForm))
+            return output
+
+
+
+
--- a/src/source/index.rst	Fri Dec 14 12:16:12 2018 +0100
+++ b/src/source/index.rst	Mon Dec 17 17:19:35 2018 +0100
@@ -57,9 +57,9 @@
    Creating new PyAMS Packages<dev_guide/overring-feature>
    Customizing site appearance <dev_guide/custom-skin>
    Understanding PyAMS forms <dev_guide/dev-form>
-   Creating new blocks <dev_guide/howto-block>
-   Creating new portlet <dev_guide/howto-portlet>
-   Creating new content type <dev_guide/howto-content>
+   Creating new Paragraph (or blocks) <dev_guide/howto-paragraph>
+   Creating new Portlet <dev_guide/howto-portlet>
+   Creating new Content type <dev_guide/howto-content>
    Creating Custom workflows <dev_guide/howto-workflowk>
    Advanced features <dev_guide/adv-features>