--- a/src/source/howto-paragraph.rst Fri Jun 01 18:27:09 2018 +0200
+++ b/src/source/howto-paragraph.rst Mon Jun 04 11:56:08 2018 +0200
@@ -10,60 +10,59 @@
In this example we will create a contact paragraph to display at the user, who to contact
1) Define a paragraph Interface
-"""""""""""""""""""""""""""""""
+-------------------------------
At first we create a new paragraph interface.
.. code-block:: python
- CONTACT_PARAGRAPH_TYPE = 'Contact'
- CONTACT_PARAGRAPH_RENDERERS = 'PyAMS.paragraph.contact.renderers'
-
-
- class IContactParagraph(IBaseParagraph):
- """Contact paragraph interface"""
-
- name = TextLine(title=_("Contact identity"),
- description=_("Name of the contact"),
- required=True)
+ CONTACT_PHONE_PARAGRAPH_TYPE = 'PhoneContact'
+ CONTACT_PHONE_PARAGRAPH_RENDERERS = 'PyAMS.paragraph.contact.phone.renderers'
- photo = ImageField(title=_("Photo"),
- description=_("Use 'browse' button to select contact picture"),
- required=False)
+ class IContactPhoneParagraph(IBaseParagraph):
+ """Contact with phone number paragraph interface"""
- address = Text(title=_("Address"), required=False)
+ name = TextLine(title=_("Contact identity"),
+ description=_("Name of the contact"),
+ required=True)
+
+ photo = ImageField(title=_("Photo"),
+ description=_("Use 'browse' button to select contact picture"),
+ required=False)
- contact_email = MailAddressField(title=_("Email address"),
- description=_("Contact email address"),
- required=False)
+ phone = TextLine(title=_("Phone Number"),
+ description=_("Name of the contact", required=False))
+
+ address = Text(title=_("Address"), required=False)
- renderer = Choice(title=_("Contact template"),
- description=_("Presentation template used for this contact"),
- vocabulary=CONTACT_PARAGRAPH_RENDERERS,
- default='default')
+ contact_email = MailAddressField(title=_("Email address"),
+ description=_("Contact email address"),
+ required=False)
+
+ renderer = Choice(title=_("Contact template"),
+ description=_("Presentation template used for this contact"),
+ vocabulary=CONTACT_PHONE_PARAGRAPH_RENDERERS,
+ default='default')
2) Implement the interface
-""""""""""""""""""""""""""
+--------------------------
An implementation of the interface
.. code-block:: python
- @implementer(IContactParagraph)
+ @implementer(IContactPhoneParagraph)
@factory_config(provided=IContactPhoneParagraph)
- class ContactParagraph(RenderedContentMixin, BaseParagraph):
+ class ContactPhoneParagraph(BaseParagraph):
"""Contact paragraph"""
- icon_class = 'fa-id-card-o'
- icon_hint = _("Contact card")
-
- name = FieldProperty(IContactParagraph['name'])
- _photo = FileProperty(IContactParagraph['photo'])
+ icon_class = 'fa-phone'
+ icon_hint = _("Phone number card")
address = FieldProperty(IContactParagraph['address'])
contact_email = FieldProperty(IContactParagraph['contact_email'])
@@ -81,7 +80,7 @@
3) renderer Vocabulary
-""""""""""""""""""""""
+----------------------
The list of rendered available for a paragraph is build automatically and is based on adapters that provide this interface
@@ -105,7 +104,7 @@
To display and manage the new paragraph in the ZMI, you should create this associated forms
1) paragraph factory
-""""""""""""""""""""
+--------------------
To create a new element inside the zodb, we need a container to this element. PyAMS provide
`IParagraphContainerTarget`, it's the default container for all paragraphs. We could use this container interface
@@ -141,9 +140,11 @@
def add(self, object):
IParagraphContainer(self.context).append(object)
+
- *JSON*
.. code-block:: python
+
@view_config(name='add-contact-paragraph.json', context=IParagraphContainerTarget, request_type=IPyAMSLayer,
permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
class ContactParagraphAJAXAddForm(BaseParagraphAJAXAddForm, ContactParagraphAddForm):
@@ -151,7 +152,7 @@
2) Append 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
@@ -167,3 +168,81 @@
url = 'add-contact-paragraph.html'
paragraph_type = CONTACT_PARAGRAPH_TYPE
+
+3)Edit form
+-----------
+
+- *HTML*
+.. code-block:: python
+
+ @pagelet_config(name='properties.html', context=IContactParagraph, layer=IPyAMSLayer,
+ permission=MANAGE_CONTENT_PERMISSION)
+ class ContactParagraphPropertiesEditForm(BaseParagraphPropertiesEditForm):
+ """Contact paragraph properties edit form"""
+
+ prefix = 'contact_properties.'
+
+ legend = _("Edit contact card properties")
+ icon_css_class = 'fa fa-fw fa-id-card-o'
+
+ fields = field.Fields(IContactParagraph).omit('__parent__', '__name__', 'visible')
+ fields['renderer'].widgetFactory = RendererFieldWidget
+
+ ajax_handler = 'properties.json'
+ edit_permission = MANAGE_CONTENT_PERMISSION
+
+ def updateWidgets(self, prefix=None):
+ super(ContactParagraphPropertiesEditForm, self).updateWidgets(prefix)
+ if 'address' in self.widgets:
+ self.widgets['address'].widget_css_class = 'textarea'
+
+ - *JSON*
+
+.. code-block:: python
+
+ @view_config(name='properties.json', context=IContactParagraph, request_type=IPyAMSLayer,
+ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+ class ContactParagraphPropertiesAJAXEditForm(BaseParagraphAJAXEditForm, ContactParagraphPropertiesEditForm):
+ """Contact paragraph properties edit form, JSON renderer"""
+
+
+ @adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IParagraphInnerEditor)
+ @implementer(IInnerForm)
+ class ContactParagraphInnerEditForm(ContactParagraphPropertiesEditForm):
+ """Contact paragraph inner edit form"""
+
+ legend = None
+ ajax_handler = 'inner-properties.json'
+
+ @property
+ def buttons(self):
+ if self.mode == INPUT_MODE:
+ return button.Buttons(IParagraphEditFormButtons)
+ else:
+ return button.Buttons()
+
+
+ @view_config(name='inner-properties.json', context=IContactParagraph, request_type=IPyAMSLayer,
+ permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True)
+ class ContactParagraphInnerAJAXEditForm(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, ())
+ 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
+
+.. note::
+
+ Select the new content block types in ZMI to make it available in tools
+
+ .. image:: _static/select_paragraph.png