58 to customize it to write that ``img`` tag, as below: |
58 to customize it to write that ``img`` tag, as below: |
59 |
59 |
60 .. sourcecode:: python |
60 .. sourcecode:: python |
61 |
61 |
62 class HTMLPageHeader(basetemplates.HTMLPageHeader): |
62 class HTMLPageHeader(basetemplates.HTMLPageHeader): |
63 # override this since it's the easier way to have our bg image |
63 # override this since it's the easier way to have our bg image |
64 # as the first element following <body> |
64 # as the first element following <body> |
65 def call(self, **kwargs): |
65 def call(self, **kwargs): |
66 self.w(u'<img id="bg-image" src="%sbackground.jpg" alt="background image"/>' |
66 self.w(u'<img id="bg-image" src="%sbackground.jpg" alt="background image"/>' |
67 % self._cw.datadir_url) |
67 % self._cw.datadir_url) |
68 super(HTMLPageHeader, self).call(**kwargs) |
68 super(HTMLPageHeader, self).call(**kwargs) |
69 |
69 |
70 |
70 |
71 def registration_callback(vreg): |
71 def registration_callback(vreg): |
72 vreg.register_all(globals().values(), __name__, (HTMLPageHeader)) |
72 vreg.register_all(globals().values(), __name__, (HTMLPageHeader)) |
73 vreg.register_and_replace(HTMLPageHeader, basetemplates.HTMLPageHeader) |
73 vreg.register_and_replace(HTMLPageHeader, basetemplates.HTMLPageHeader) |
74 |
74 |
75 |
75 |
76 As you may have guessed, my background image is in a :file:`background.jpg` file |
76 As you may have guessed, my background image is in a :file:`background.jpg` file |
77 in the cube's :file:`data` directory, but there are still some things to explain |
77 in the cube's :file:`data` directory, but there are still some things to explain |
78 to newcomers here: |
78 to newcomers here: |
214 from logilab.common.decorators import monkeypatch |
215 from logilab.common.decorators import monkeypatch |
215 from cubicweb import ValidationError |
216 from cubicweb import ValidationError |
216 from cubicweb.web.views import uicfg, component |
217 from cubicweb.web.views import uicfg, component |
217 from cubicweb.web.views import basecontrollers |
218 from cubicweb.web.views import basecontrollers |
218 |
219 |
|
220 |
219 # hide displayed_on relation using uicfg since it will be displayed by the box below |
221 # hide displayed_on relation using uicfg since it will be displayed by the box below |
220 uicfg.primaryview_section.tag_object_of(('*', 'displayed_on', '*'), 'hidden') |
222 uicfg.primaryview_section.tag_object_of(('*', 'displayed_on', '*'), 'hidden') |
221 |
223 |
|
224 |
222 class PersonBox(component.AjaxEditRelationCtxComponent): |
225 class PersonBox(component.AjaxEditRelationCtxComponent): |
223 __regid__ = 'sytweb.displayed-on-box' |
226 __regid__ = 'sytweb.displayed-on-box' |
224 # box position |
227 # box position |
225 order = 101 |
228 order = 101 |
226 context = 'left' |
229 context = 'left' |
227 # define relation to be handled |
230 # define relation to be handled |
228 rtype = 'displayed_on' |
231 rtype = 'displayed_on' |
229 role = 'object' |
232 role = 'object' |
230 target_etype = 'Person' |
233 target_etype = 'Person' |
231 # messages |
234 # messages |
232 added_msg = _('person has been added') |
235 added_msg = _('person has been added') |
233 removed_msg = _('person has been removed') |
236 removed_msg = _('person has been removed') |
234 # bind to js_* methods of the json controller |
237 # bind to js_* methods of the json controller |
235 fname_vocabulary = 'unrelated_persons' |
238 fname_vocabulary = 'unrelated_persons' |
236 fname_validate = 'link_to_person' |
239 fname_validate = 'link_to_person' |
237 fname_remove = 'unlink_person' |
240 fname_remove = 'unlink_person' |
238 |
241 |
239 |
242 |
240 @monkeypatch(basecontrollers.JSonController) |
243 @monkeypatch(basecontrollers.JSonController) |
241 @basecontrollers.jsonize |
244 @basecontrollers.jsonize |
242 def js_unrelated_persons(self, eid): |
245 def js_unrelated_persons(self, eid): |
243 """return tag unrelated to an entity""" |
246 """return tag unrelated to an entity""" |
244 rql = "Any F + ' ' + S WHERE P surname S, P firstname F, X eid %(x)s, NOT P displayed_on X" |
247 rql = "Any F + ' ' + S WHERE P surname S, P firstname F, X eid %(x)s, NOT P displayed_on X" |
245 return [name for (name,) in self._cw.execute(rql, {'x' : eid})] |
248 return [name for (name,) in self._cw.execute(rql, {'x' : eid})] |
246 |
249 |
247 |
250 |
248 @monkeypatch(basecontrollers.JSonController) |
251 @monkeypatch(basecontrollers.JSonController) |
249 def js_link_to_person(self, eid, people): |
252 def js_link_to_person(self, eid, people): |
250 req = self._cw |
253 req = self._cw |
251 for name in people: |
254 for name in people: |
252 name = name.strip().title() |
255 name = name.strip().title() |
253 if not name: |
256 if not name: |
254 continue |
257 continue |
255 try: |
258 try: |
256 firstname, surname = name.split(None, 1) |
259 firstname, surname = name.split(None, 1) |
257 except: |
260 except: |
258 raise ValidationError(eid, {('displayed_on', 'object'): 'provide <first name> <surname>'}) |
261 raise ValidationError(eid, {('displayed_on', 'object'): 'provide <first name> <surname>'}) |
259 rset = req.execute('Person P WHERE ' |
262 rset = req.execute('Person P WHERE ' |
260 'P firstname %(firstname)s, P surname %(surname)s', |
263 'P firstname %(firstname)s, P surname %(surname)s', |
261 locals()) |
264 locals()) |
262 if rset: |
265 if rset: |
263 person = rset.get_entity(0, 0) |
266 person = rset.get_entity(0, 0) |
264 else: |
267 else: |
265 person = req.create_entity('Person', firstname=firstname, |
268 person = req.create_entity('Person', firstname=firstname, |
266 surname=surname) |
269 surname=surname) |
267 req.execute('SET P displayed_on X WHERE ' |
270 req.execute('SET P displayed_on X WHERE ' |
268 'P eid %(p)s, X eid %(x)s, NOT P displayed_on X', |
271 'P eid %(p)s, X eid %(x)s, NOT P displayed_on X', |
269 {'p': person.eid, 'x' : eid}) |
272 {'p': person.eid, 'x' : eid}) |
|
273 |
270 |
274 |
271 @monkeypatch(basecontrollers.JSonController) |
275 @monkeypatch(basecontrollers.JSonController) |
272 def js_unlink_person(self, eid, personeid): |
276 def js_unlink_person(self, eid, personeid): |
273 self._cw.execute('DELETE P displayed_on X WHERE P eid %(p)s, X eid %(x)s', |
277 self._cw.execute('DELETE P displayed_on X WHERE P eid %(p)s, X eid %(x)s', |
274 {'p': personeid, 'x': eid}) |
278 {'p': personeid, 'x': eid}) |
275 |
279 |
276 |
280 |
277 You basically subclass to configure with some class attributes. The `fname_*` |
281 You basically subclass to configure with some class attributes. The `fname_*` |
278 attributes give the name of methods that should be defined on the json control to |
282 attributes give the name of methods that should be defined on the json control to |
279 make the AJAX part of the widget work: one to get the vocabulary, one to add a |
283 make the AJAX part of the widget work: one to get the vocabulary, one to add a |
325 |
329 |
326 .. sourcecode:: python |
330 .. sourcecode:: python |
327 |
331 |
328 from cubicweb.web import facet |
332 from cubicweb.web import facet |
329 |
333 |
|
334 |
330 class DisplayedOnFacet(facet.RelationFacet): |
335 class DisplayedOnFacet(facet.RelationFacet): |
331 __regid__ = 'displayed_on-facet' |
336 __regid__ = 'displayed_on-facet' |
332 # relation to be displayed |
337 # relation to be displayed |
333 rtype = 'displayed_on' |
338 rtype = 'displayed_on' |
334 role = 'object' |
339 role = 'object' |
335 # view to use to display persons |
340 # view to use to display persons |
336 label_vid = 'combobox' |
341 label_vid = 'combobox' |
337 |
342 |
338 Let's say we also want to filter according to the `visibility` attribute. This is |
343 Let's say we also want to filter according to the `visibility` attribute. This is |
339 even simpler as we just have to derive from the :class:`AttributeFacet` class: |
344 even simpler as we just have to derive from the :class:`AttributeFacet` class: |
340 |
345 |
341 .. sourcecode:: python |
346 .. sourcecode:: python |
342 |
347 |
343 class VisibilityFacet(facet.AttributeFacet): |
348 class VisibilityFacet(facet.AttributeFacet): |
344 __regid__ = 'visibility-facet' |
349 __regid__ = 'visibility-facet' |
345 rtype = 'visibility' |
350 rtype = 'visibility' |
346 |
351 |
347 Now if I search for some pictures on my site, I get the following facets available: |
352 Now if I search for some pictures on my site, I get the following facets available: |
348 |
353 |
349 .. image:: ../../images/tutos-photowebsite_facets.png |
354 .. image:: ../../images/tutos-photowebsite_facets.png |
350 |
355 |