Updated forms doc doc-dc
authorDamien Correia
Fri, 08 Jun 2018 17:57:18 +0200
branchdoc-dc
changeset 85 82165875e66b
parent 84 8eb1b401003a
child 86 f7b0435b26cf
Updated forms doc
src/source/appextend.rst
src/source/howto-form.rst
src/source/howto-paragraph.rst
src/source/howto-skin.rst
--- a/src/source/appextend.rst	Tue Jun 05 17:14:19 2018 +0200
+++ b/src/source/appextend.rst	Fri Jun 08 17:57:18 2018 +0200
@@ -7,8 +7,10 @@
 .. toctree::
     :maxdepth: 1
 
+
     howto-adapter
+    howto-form
+    howto-paragraph
     howto-portlet
     howto-renderer
-    howto-paragraph
     howto-skin
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/source/howto-form.rst	Fri Jun 08 17:57:18 2018 +0200
@@ -0,0 +1,103 @@
+.. _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:method:`@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/howto-paragraph.rst	Tue Jun 05 17:14:19 2018 +0200
+++ b/src/source/howto-paragraph.rst	Fri Jun 08 17:57:18 2018 +0200
@@ -106,18 +106,35 @@
 1) Paragraph factory
 --------------------
 
-To create a new element inside the zodb, we need a container to this element. PyAMS provide
+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.
 
-We need to create two views
 
-- *HTML*
+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
+
+
+Definition of a form to create a new ContactPhone instance
+
+.. 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 phone paragraph add form"""
 
@@ -126,7 +143,6 @@
         icon_css_class = 'fa fa-fw fa-phone'
 
         fields = field.Fields(IContactPhoneParagraph).omit('__parent__', '__name__', 'visible')
-        ajax_handler = 'add-contact-phone-paragraph.json' #(*)
         edit_permission = MANAGE_CONTENT_PERMISSION
 
          def create(self, data):
@@ -136,18 +152,7 @@
             IParagraphContainer(self.context).append(object)
 
 
-- *JSON*
-
-.. code-block:: python
-
-    #(*)
-    @view_config(name='add-contact-phone-1paragraph.json', context=IParagraphContainerTarget, request_type=IPyAMSLayer,
-                 permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
-    class ContactPhoneParagraphAJAXAddForm(BaseParagraphAJAXAddForm, ContactPhoneParagraphAddForm):
-        """Contact phone paragraph add form, JSON renderer"""
-
-
-2) Append the paragraph addform button in the menu
+2) Create the Paragraph addform button in the menu
 --------------------------------------------------
 
 We have created a new form and we want add a quick access button to create a new paragraph
@@ -166,18 +171,20 @@
 
 
 
-3) Create Edit form
--------------------
+3) Create Edit inner 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
-        ajax_handler = 'inner-properties.json'
 
         @property
         def buttons(self):
@@ -186,15 +193,6 @@
             else:
                 return button.Buttons()
 
-
-
-.. code-block:: python
-
-    @view_config(name='inner-properties.json', context=IContactPhoneParagraph, request_type=IPyAMSLayer,
-                 permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
-    class ContactPhoneParagraphInnerAJAXEditForm(BaseParagraphAJAXEditForm, ContactParagraphInnerEditForm):
-        """Contact paragraph inner edit form, JSON renderer"""
-
         def get_ajax_output(self, changes):
             output = super(ContactParagraphInnerAJAXEditForm, self).get_ajax_output(changes)
             updated = changes.get(IBaseParagraph, ())
@@ -216,10 +214,10 @@
 This form is used inside modals popup
 
 
-- *HTML*
-
 .. code-block:: python
 
+    @ajax_config(name='properties.json', context=IContactPhoneParagraph, request_type=IPyAMSLayer,
+                     permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
     @pagelet_config(name='properties.html', context=IContactParagraph, layer=IPyAMSLayer,
                     permission=MANAGE_CONTENT_PERMISSION)
     class ContactPhoneParagraphPropertiesEditForm(BaseParagraphPropertiesEditForm):
@@ -233,22 +231,95 @@
         fields = field.Fields(IContactParagraph).omit('__parent__', '__name__', 'visible')
         fields['renderer'].widgetFactory = RendererFieldWidget
 
-        ajax_handler = 'properties.json'
         edit_permission = MANAGE_CONTENT_PERMISSION
 
 
-- *JSON*
-
-.. code-block:: python
-
-    @view_config(name='properties.json', context=IContactPhoneParagraph, request_type=IPyAMSLayer,
-                 permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
-    class ContactPhoneParagraphPropertiesAJAXEditForm(BaseParagraphAJAXEditForm, ContactParagraphPropertiesEditForm):
-        """Contact phone paragraph properties edit form, JSON renderer"""
-
-
 .. note::
 
     Select the new content block types in ZMI to make it available in tools
 
     .. image:: _static/select_paragraph.png
+
+
+How to associate links or Illustrations to a Paragraph ?
+========================================================
+
+Adding the following marker interface, we add new behavior to the Paragraph `ContactPhoneParagraph` .
+
+
+1) Inner form
+-------------
+
+.. code-block:: python
+
+    @adapter_config(context=(IContactPhoneParagraph, IPyAMSLayer), provides=IParagraphInnerEditor)
+    @implementer(IInnerForm, IPropertiesEditForm, IAssociationParentForm)
+    class ContactPhoneParagraphInnerEditForm(ContactPhoneParagraphPropertiesEditForm):
+        """Contact paragraph inner edit form"""
+
+        legend = None
+        ajax_handler = 'inner-properties.json'
+
+
+Marker interfaces:
+
+:py:class:`IPropertiesEditForm`
+
+:py:class:`IAssociationParentForm`
+
+
+.. image:: _static/associations_form.png
+
+
+
+2) Inside a dedicated menu
+--------------------------
+
+.. image:: _static/select_links_n_attachment.png
+
+
+.. code-block:: python
+
+    @implementer(IContactPhoneParagraph, IIllustrationTarget,ILinkContainerTarget,IExtFileContainerTarget))
+    @factory_config(provided=IContactPhoneParagraph)
+    class ContactPhoneParagraph(BaseParagraph):
+        """Contact paragraph"""
+            ...
+
+
+Marker interfaces:
+
+    +--------------------------------+
+    |:py:class:`IIllustrationTarget` |
+    +===================+============+
+    |                   |            |
+    +-------------------+------------+
+
+    +---------------------------------+
+    |:py:class:`ILinkContainerTarget` |
+    +==============+==================+
+    |              | Add internal link|
+    |              +------------------+
+    |              | Add external link|
+    |              +------------------+
+    |              | Add mailto link  |
+    +--------------+------------------+
+
+    +------------------------------------+
+    |:py:class:`IExtFileContainerTarget` |
+    +================+===================+
+    |                | Add external file |
+    |                +-------------------+
+    |                | Add image         |
+    |                +-------------------+
+    |                | Add video         |
+    |                +-------------------+
+    |                | Add audio file    |
+    +----------------+-------------------+
+
+
+ZMI overview:
+.. image:: _static/select_add_links.png
+
+
+
--- a/src/source/howto-skin.rst	Tue Jun 05 17:14:19 2018 +0200
+++ b/src/source/howto-skin.rst	Fri Jun 08 17:57:18 2018 +0200
@@ -28,7 +28,7 @@
                         )
 
 
-Resource can include other resource already defined in pyams_default_theme
+:py:class:`Resource` can include others resources already defined with *depends* attribute, here `pyams_default_theme`.
 
 
 2) Create a new Layer to your skin