diff -r d7dd088ed557 -r 097b0c025eec src/source/developer_guide/howto-paragraph.rst --- a/src/source/developer_guide/howto-paragraph.rst Tue Dec 11 16:43:45 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,345 +0,0 @@ -.. _paragraphhowto: - - -How to create a Paragraph type? -=============================== - -Paragraphs or Blocks are components that contain elements/fields and provide one or many renderer methods to compose -the front office website - - -Create a Paragraph -"""""""""""""""""" - -In this example we will create a contact paragraph to display at the user, who to contact. - -1) Interface ------------- - -At first we create a new paragraph interface. - -.. code-block:: python - - CONTACT_PHONE_PARAGRAPH_TYPE = 'PhoneContact' - CONTACT_PHONE_PARAGRAPH_RENDERERS = 'PyAMS.paragraph.contact.phone.renderers' - - - class IContactPhoneParagraph(IBaseParagraph): - """Contact with phone number 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) - - phone = TextLine(title=_("Phone Number"), - description=_("Name of the contact", 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(IContactPhoneParagraph) - @factory_config(provided=IContactPhoneParagraph) - class ContactPhoneParagraph(BaseParagraph): - """Contact paragraph""" - - - icon_class = 'fa-phone' - icon_hint = _("Phone number card") - - name = FieldProperty(IContactPhoneParagraph['name']) - _photo = FileProperty(IContactPhoneParagraph['photo']) - - 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) Renderers 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 Phone paragraph renderers vocabulary""" - - content_interface = IContactPhoneParagraph - - -.. seealso:: - - :ref:`rendererhowto` - - -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 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 - - @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""" - - legend = _("Add new contact phone card") - dialog_class = 'modal-large' - icon_css_class = 'fa fa-fw fa-phone' - - fields = field.Fields(IContactPhoneParagraph).omit('__parent__', '__name__', 'visible') - edit_permission = MANAGE_CONTENT_PERMISSION - - def create(self, data): - return ContactPhoneParagraph() - - def add(self, object): - IParagraphContainer(self.context).append(object) - - -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 - -.. code-block:: python - - @viewlet_config(name='add-contact-phone-paragraph.menu', context=IParagraphContainerTarget, view=IParagraphContainerView, - layer=IPyAMSLayer, manager=IToolbarAddingMenu, weight=600) - class ContactPhoneParagraphAddMenu(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 - - - -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 - - @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 - - -4) Create an Edit modal form ------------------------------ - -This form is used inside modals popup - - -.. 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): - """Contact phone 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 - - edit_permission = MANAGE_CONTENT_PERMISSION - - -.. 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` . - - -Paragraph advanced -"""""""""""""""""" - -You can attach Associated files, links or illustration and manage them directly through the rubric `Links and Attachments`. - -.. image:: _static/select_links_n_attachment.png - - -1) Paragraph with Links and Attachements ----------------------------------------- - -To "activate" this features the paragrath object must to implement specific interface - - -.. code-block:: python - - @implementer(IContactPhoneParagraph, IIllustrationTarget,ILinkContainerTarget,IExtFileContainerTarget)) - @factory_config(provided=IContactPhoneParagraph) - class ContactPhoneParagraph(BaseParagraph): - """Contact paragraph""" - ... - - -These interfaces will allow to link other data to the 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 - - - -2) Add link and association form --------------------------------- - -You can add form to manage links and attachments directly in paragraph form to do that your form must implement -``IPropertiesEditForm`` and/or ``IAssociationParentForm`` - - -.. 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` | -+=========+=========================+ -| | Add Illustration form | -+---------+-------------------------+ - -+-----------------------------------+ -|:py:class:`IAssociationParentForm` | -+===========+=======================+ -| | Add Association form | -+-----------+-----------------------+ - -.. image:: _static/associations_form.png -