# HG changeset patch # User Damien Correia # Date 1527507930 -7200 # Node ID a3a8642a31b2a213524d9b55c232df085c993966 # Parent 3f403b9c42202c6966d45def097700f02773a80d Updated Paragraph doc diff -r 3f403b9c4220 -r a3a8642a31b2 src/source/appextend.rst --- a/src/source/appextend.rst Fri May 25 15:23:31 2018 +0200 +++ b/src/source/appextend.rst Mon May 28 13:45:30 2018 +0200 @@ -10,3 +10,4 @@ howto-adapter howto-portlet howto-renderer + howto-paragraph diff -r 3f403b9c4220 -r a3a8642a31b2 src/source/howto-paragraph.rst --- a/src/source/howto-paragraph.rst Fri May 25 15:23:31 2018 +0200 +++ b/src/source/howto-paragraph.rst Mon May 28 13:45:30 2018 +0200 @@ -3,3 +3,167 @@ How to create a new paragraph type? =================================== + +Paragraphs are components or blocs that contain elements/fields and provide one or many renderer methods to compose +the front office website + +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) + + + photo = ImageField(title=_("Photo"), + description=_("Use 'browse' button to select contact picture"), + required=False) + + address = Text(title=_("Address"), required=False) + + 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_PARAGRAPH_RENDERERS, + default='default') + + + + +2) Implement the interface +"""""""""""""""""""""""""" + +An implementation of the interface + +.. code-block:: python + + @implementer(IContactParagraph) + @factory_config(provided=IContactPhoneParagraph) + class ContactParagraph(RenderedContentMixin, BaseParagraph): + """Contact paragraph""" + + + icon_class = 'fa-id-card-o' + icon_hint = _("Contact card") + + name = FieldProperty(IContactParagraph['name']) + _photo = FileProperty(IContactParagraph['photo']) + + address = FieldProperty(IContactParagraph['address']) + contact_email = FieldProperty(IContactParagraph['contact_email']) + renderer = FieldProperty(IContactParagraph['renderer']) + + @property + def photo(self): + return self._photo + + @photo.setter + def photo(self, value): + self._photo = value + if IImage.providedBy(self._photo): + alsoProvides(self._photo, IResponsiveImage) + + +3) renderer Vocabulary +"""""""""""""""""""""" + +The list of rendered available for a paragraph is build automatically and is based on adapters that provide this interface + +.. code-block:: python + + @vocabulary_config(name=CONTACT_PARAGRAPH_RENDERERS) + class ContactParagraphRendererVocabulary(RenderersVocabulary): + """Contact paragraph renderers vocabulary""" + + content_interface = IContactParagraph + + +.. seealso:: + + :ref:`rendererhowto` + + +How integrate a paragraph in the ZMI? +===================================== + +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 +as context to create a new paragraph. + +We need to create two views + +- *HTML* + +.. code-block:: python + + @pagelet_config(name='add-contact-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, + permission=MANAGE_CONTENT_PERMISSION) + class ContactParagraphAddForm(AdminDialogAddForm): + """Contact paragraph add form""" + + legend = _("Add new contact card") + dialog_class = 'modal-large' + icon_css_class = 'fa fa-fw fa-id-card-o' + + fields = field.Fields(IContactParagraph).omit('__parent__', '__name__', 'visible') + ajax_handler = 'add-contact-paragraph.json' + edit_permission = MANAGE_CONTENT_PERMISSION + + def updateWidgets(self, prefix=None): + super(ContactParagraphAddForm, self).updateWidgets(prefix) + if 'address' in self.widgets: + self.widgets['address'].widget_css_class = 'textarea' + + def create(self, data): + return ContactParagraph() + + 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): + """Contact paragraph add form, JSON renderer""" + + +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 + +.. code-block:: python + + @viewlet_config(name='add-contact-paragraph.menu', context=IParagraphContainerTarget, view=IParagraphContainerView, + layer=IPyAMSLayer, manager=IToolbarAddingMenu, weight=600) + class ContactParagraphAddMenu(BaseParagraphAddMenu): + """Contact paragraph add menu""" + + label = _("Contact card...") + label_css_class = 'fa fa-fw fa-id-card-o' + url = 'add-contact-paragraph.html' + paragraph_type = CONTACT_PARAGRAPH_TYPE +