31 |
31 |
32 from rql import nodes |
32 from rql import nodes |
33 |
33 |
34 from logilab.mtconverter import TransformError, xml_escape, xml_escape |
34 from logilab.mtconverter import TransformError, xml_escape, xml_escape |
35 |
35 |
36 from cubicweb import NoSelectableObject |
36 from cubicweb import NoSelectableObject, tags |
37 from cubicweb.selectors import yes, empty_rset, one_etype_rset |
37 from cubicweb.selectors import yes, empty_rset, one_etype_rset, match_kwargs |
38 from cubicweb.schema import display_name |
38 from cubicweb.schema import display_name |
39 from cubicweb.view import EntityView, AnyRsetView, View |
39 from cubicweb.view import EntityView, AnyRsetView, View |
40 from cubicweb.uilib import cut, printable_value |
40 from cubicweb.uilib import cut, printable_value |
|
41 from cubicweb.web.views import calendar |
41 |
42 |
42 |
43 |
43 class NullView(AnyRsetView): |
44 class NullView(AnyRsetView): |
44 """default view when no result has been found""" |
45 """default view when no result has been found""" |
45 __regid__ = 'null' |
46 __regid__ = 'null' |
434 XmlItemView = class_moved(xmlrss.XMLItemView) |
435 XmlItemView = class_moved(xmlrss.XMLItemView) |
435 XmlRsetView = class_moved(xmlrss.XMLRsetView) |
436 XmlRsetView = class_moved(xmlrss.XMLRsetView) |
436 RssView = class_moved(xmlrss.RSSView) |
437 RssView = class_moved(xmlrss.RSSView) |
437 RssItemView = class_moved(xmlrss.RSSItemView) |
438 RssItemView = class_moved(xmlrss.RSSItemView) |
438 |
439 |
|
440 |
|
441 class GroupByView(EntityView): |
|
442 """grouped view of a result set. The `group_key` method return the group |
|
443 key of an entities (a string or tuple of string). |
|
444 |
|
445 For each group, display a link to entities of this group by generating url |
|
446 like <basepath>/<key> or <basepath>/<key item 1>/<key item 2>. |
|
447 """ |
|
448 __abstrack__ = True |
|
449 __select__ = EntityView.__select__ & match_kwargs('basepath') |
|
450 entity_attribute = None |
|
451 reversed = False |
|
452 |
|
453 def index_url(self, basepath, key, **kwargs): |
|
454 if isinstance(key, (list, tuple)): |
|
455 key = '/'.join(key) |
|
456 return self._cw.build_url('%s/%s' % (basepath, key), |
|
457 **kwargs) |
|
458 |
|
459 def index_link(self, basepath, key, items): |
|
460 url = self.index_url(basepath, key) |
|
461 if isinstance(key, (list, tuple)): |
|
462 key = ' '.join(key) |
|
463 return tags.a(key, href=url) |
|
464 |
|
465 def group_key(self, entity, **kwargs): |
|
466 value = getattr(entity, self.entity_attribute) |
|
467 if callable(value): |
|
468 value = value() |
|
469 return value |
|
470 |
|
471 def call(self, basepath, maxentries=None, **kwargs): |
|
472 index = {} |
|
473 for entity in self.cw_rset.entities(): |
|
474 index.setdefault(self.group_key(entity, **kwargs), []).append(entity) |
|
475 displayed = sorted(index) |
|
476 if self.reversed: |
|
477 displayed = reversed(displayed) |
|
478 if maxentries is None: |
|
479 needmore = False |
|
480 else: |
|
481 needmore = len(index) > maxentries |
|
482 displayed = tuple(displayed)[:maxentries] |
|
483 w = self.w |
|
484 w(u'<ul class="boxListing">') |
|
485 for key in displayed: |
|
486 w(u'<li>%s</li>\n' % |
|
487 self.index_link(basepath, key, index[key])) |
|
488 if needmore: |
|
489 url = self._cw.build_url('view', vid=self.__regid__, |
|
490 rql=self.cw_rset.printable_rql()) |
|
491 w( u'<li>%s</li>\n' % tags.a(u'[%s]' % self._cw._('see more'), |
|
492 href=url)) |
|
493 w(u'</ul>\n') |
|
494 |
|
495 |
|
496 class ArchiveView(GroupByView): |
|
497 """archive view of a result set. Links to months are built using a basepath |
|
498 parameters, eg using url like <basepath>/<year>/<month> |
|
499 """ |
|
500 __regid__ = 'cw.archive.by_date' |
|
501 entity_attribute = 'creation_date' |
|
502 reversed = True |
|
503 |
|
504 def group_key(self, entity, **kwargs): |
|
505 value = super(ArchiveView, self).group_key(entity, **kwargs) |
|
506 return '%04d' % value.year, '%02d' % value.month |
|
507 |
|
508 def index_link(self, basepath, key, items): |
|
509 """represent a single month entry""" |
|
510 year, month = key |
|
511 label = u'%s %s [%s]' % (self._cw._(calendar.MONTHNAMES[int(month)-1]), |
|
512 year, len(items)) |
|
513 etypes = set(entity.__regid__ for entity in items) |
|
514 vtitle = '%s %s' % (', '.join(display_name(self._cw, etype, 'plural') |
|
515 for etype in etypes), |
|
516 label) |
|
517 title = self._cw._('archive for %(month)s/%(year)s') % { |
|
518 'month': month, 'year': year} |
|
519 url = self.index_url(basepath, key, vtitle=vtitle) |
|
520 return tags.a(label, href=url, title=title) |
|
521 |
|
522 |
|
523 class AuthorView(GroupByView): |
|
524 """author view of a result set. Links to month are built using a basepath |
|
525 parameters, eg using url like <basepath>/<author> |
|
526 """ |
|
527 __regid__ = 'cw.archive.by_author' |
|
528 entity_attribute = 'creator' |
|
529 |
|
530 def group_key(self, entity, **kwargs): |
|
531 value = super(AuthorView, self).group_key(entity, **kwargs) |
|
532 if value: |
|
533 return value.login |
|
534 return value |
|
535 |
|
536 def index_link(self, basepath, key, items): |
|
537 label = u'%s [%s]' % (key, len(items)) |
|
538 etypes = set(entity.__regid__ for entity in items) |
|
539 vtitle = self._cw._('%(etype)s by %(author)s') % { |
|
540 'etype': ', '.join(display_name(self._cw, etype, 'plural') |
|
541 for etype in etypes), |
|
542 'author': label} |
|
543 url = self.index_url(basepath, key, vtitle=vtitle) |
|
544 title = self._cw._('archive for %(author)s') % {'author': key} |
|
545 return tags.a(label, href=url, title=title) |