1 .. _paragraphhowto: |
1 .. _paragraphhowto: |
2 |
2 |
3 |
3 |
4 How to create a new paragraph type? |
4 How to create a new paragraph type? |
5 =================================== |
5 =================================== |
|
6 |
|
7 Paragraphs are components or blocs that contain elements/fields and provide one or many renderer methods to compose |
|
8 the front office website |
|
9 |
|
10 In this example we will create a contact paragraph to display at the user, who to contact |
|
11 |
|
12 1) Define a paragraph Interface |
|
13 """"""""""""""""""""""""""""""" |
|
14 |
|
15 At first we create a new paragraph interface. |
|
16 |
|
17 .. code-block:: python |
|
18 |
|
19 CONTACT_PARAGRAPH_TYPE = 'Contact' |
|
20 CONTACT_PARAGRAPH_RENDERERS = 'PyAMS.paragraph.contact.renderers' |
|
21 |
|
22 |
|
23 class IContactParagraph(IBaseParagraph): |
|
24 """Contact paragraph interface""" |
|
25 |
|
26 name = TextLine(title=_("Contact identity"), |
|
27 description=_("Name of the contact"), |
|
28 required=True) |
|
29 |
|
30 |
|
31 photo = ImageField(title=_("Photo"), |
|
32 description=_("Use 'browse' button to select contact picture"), |
|
33 required=False) |
|
34 |
|
35 address = Text(title=_("Address"), required=False) |
|
36 |
|
37 contact_email = MailAddressField(title=_("Email address"), |
|
38 description=_("Contact email address"), |
|
39 required=False) |
|
40 |
|
41 renderer = Choice(title=_("Contact template"), |
|
42 description=_("Presentation template used for this contact"), |
|
43 vocabulary=CONTACT_PARAGRAPH_RENDERERS, |
|
44 default='default') |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 2) Implement the interface |
|
50 """""""""""""""""""""""""" |
|
51 |
|
52 An implementation of the interface |
|
53 |
|
54 .. code-block:: python |
|
55 |
|
56 @implementer(IContactParagraph) |
|
57 @factory_config(provided=IContactPhoneParagraph) |
|
58 class ContactParagraph(RenderedContentMixin, BaseParagraph): |
|
59 """Contact paragraph""" |
|
60 |
|
61 |
|
62 icon_class = 'fa-id-card-o' |
|
63 icon_hint = _("Contact card") |
|
64 |
|
65 name = FieldProperty(IContactParagraph['name']) |
|
66 _photo = FileProperty(IContactParagraph['photo']) |
|
67 |
|
68 address = FieldProperty(IContactParagraph['address']) |
|
69 contact_email = FieldProperty(IContactParagraph['contact_email']) |
|
70 renderer = FieldProperty(IContactParagraph['renderer']) |
|
71 |
|
72 @property |
|
73 def photo(self): |
|
74 return self._photo |
|
75 |
|
76 @photo.setter |
|
77 def photo(self, value): |
|
78 self._photo = value |
|
79 if IImage.providedBy(self._photo): |
|
80 alsoProvides(self._photo, IResponsiveImage) |
|
81 |
|
82 |
|
83 3) renderer Vocabulary |
|
84 """""""""""""""""""""" |
|
85 |
|
86 The list of rendered available for a paragraph is build automatically and is based on adapters that provide this interface |
|
87 |
|
88 .. code-block:: python |
|
89 |
|
90 @vocabulary_config(name=CONTACT_PARAGRAPH_RENDERERS) |
|
91 class ContactParagraphRendererVocabulary(RenderersVocabulary): |
|
92 """Contact paragraph renderers vocabulary""" |
|
93 |
|
94 content_interface = IContactParagraph |
|
95 |
|
96 |
|
97 .. seealso:: |
|
98 |
|
99 :ref:`rendererhowto` |
|
100 |
|
101 |
|
102 How integrate a paragraph in the ZMI? |
|
103 ===================================== |
|
104 |
|
105 To display and manage the new paragraph in the ZMI, you should create this associated forms |
|
106 |
|
107 1) paragraph factory |
|
108 """""""""""""""""""" |
|
109 |
|
110 To create a new element inside the zodb, we need a container to this element. PyAMS provide |
|
111 `IParagraphContainerTarget`, it's the default container for all paragraphs. We could use this container interface |
|
112 as context to create a new paragraph. |
|
113 |
|
114 We need to create two views |
|
115 |
|
116 - *HTML* |
|
117 |
|
118 .. code-block:: python |
|
119 |
|
120 @pagelet_config(name='add-contact-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer, |
|
121 permission=MANAGE_CONTENT_PERMISSION) |
|
122 class ContactParagraphAddForm(AdminDialogAddForm): |
|
123 """Contact paragraph add form""" |
|
124 |
|
125 legend = _("Add new contact card") |
|
126 dialog_class = 'modal-large' |
|
127 icon_css_class = 'fa fa-fw fa-id-card-o' |
|
128 |
|
129 fields = field.Fields(IContactParagraph).omit('__parent__', '__name__', 'visible') |
|
130 ajax_handler = 'add-contact-paragraph.json' |
|
131 edit_permission = MANAGE_CONTENT_PERMISSION |
|
132 |
|
133 def updateWidgets(self, prefix=None): |
|
134 super(ContactParagraphAddForm, self).updateWidgets(prefix) |
|
135 if 'address' in self.widgets: |
|
136 self.widgets['address'].widget_css_class = 'textarea' |
|
137 |
|
138 def create(self, data): |
|
139 return ContactParagraph() |
|
140 |
|
141 def add(self, object): |
|
142 IParagraphContainer(self.context).append(object) |
|
143 |
|
144 - *JSON* |
|
145 |
|
146 .. code-block:: python |
|
147 @view_config(name='add-contact-paragraph.json', context=IParagraphContainerTarget, request_type=IPyAMSLayer, |
|
148 permission=MANAGE_CONTENT_PERMISSION, renderer='json', xhr=True) |
|
149 class ContactParagraphAJAXAddForm(BaseParagraphAJAXAddForm, ContactParagraphAddForm): |
|
150 """Contact paragraph add form, JSON renderer""" |
|
151 |
|
152 |
|
153 2) Append the paragraph addform button in the menu |
|
154 """""""""""""""""""""""""""""""""""""""""""""""""" |
|
155 |
|
156 We have created a new form and we want add a quick access button to create a new paragraph |
|
157 |
|
158 .. code-block:: python |
|
159 |
|
160 @viewlet_config(name='add-contact-paragraph.menu', context=IParagraphContainerTarget, view=IParagraphContainerView, |
|
161 layer=IPyAMSLayer, manager=IToolbarAddingMenu, weight=600) |
|
162 class ContactParagraphAddMenu(BaseParagraphAddMenu): |
|
163 """Contact paragraph add menu""" |
|
164 |
|
165 label = _("Contact card...") |
|
166 label_css_class = 'fa fa-fw fa-id-card-o' |
|
167 url = 'add-contact-paragraph.html' |
|
168 paragraph_type = CONTACT_PARAGRAPH_TYPE |
|
169 |